Annotation of OpenXM_contrib/gmp/mpf/ui_sub.c, Revision 1.1.1.1
1.1 maekawa 1: /* mpf_ui_sub -- Subtract a float from an unsigned long int.
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_ui_sub (mpf_ptr r, unsigned long int u, mpf_srcptr v)
28: #else
29: mpf_ui_sub (r, u, v)
30: mpf_ptr r;
31: unsigned long int 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 uexp;
40: mp_size_t ediff;
41: int negate;
42: mp_limb_t ulimb;
43: TMP_DECL (marker);
44:
45: vsize = v->_mp_size;
46:
47: /* Handle special cases that don't work in generic code below. */
48: if (u == 0)
49: {
50: mpf_neg (r, v);
51: return;
52: }
53: if (vsize == 0)
54: {
55: mpf_set_ui (r, u);
56: return;
57: }
58:
59: /* If signs of U and V are different, perform addition. */
60: if (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_ui (r, &v_negated, u);
67: return;
68: }
69:
70: TMP_MARK (marker);
71:
72: /* Signs are now known to be the same. */
73:
74: ulimb = u;
75: /* Make U be the operand with the largest exponent. */
76: if (1 < v->_mp_exp)
77: {
78: negate = 1;
79: usize = ABS (vsize);
80: vsize = 1;
81: up = v->_mp_d;
82: vp = &ulimb;
83: rp = r->_mp_d;
84: prec = r->_mp_prec + 1;
85: uexp = v->_mp_exp;
86: ediff = uexp - 1;
87: }
88: else
89: {
90: negate = 0;
91: usize = 1;
92: vsize = ABS (vsize);
93: up = &ulimb;
94: vp = v->_mp_d;
95: rp = r->_mp_d;
96: prec = r->_mp_prec;
97: uexp = 1;
98: ediff = 1 - v->_mp_exp;
99: }
100:
101: /* Ignore leading limbs in U and V that are equal. Doing
102: this helps increase the precision of the result. */
103: if (ediff == 0)
104: {
105: /* This loop normally exits immediately. Optimize for that. */
106: for (;;)
107: {
108: usize--;
109: vsize--;
110: if (up[usize] != vp[vsize])
111: break;
112: uexp--;
113: if (usize == 0)
114: goto Lu0;
115: if (vsize == 0)
116: goto Lv0;
117: }
118: usize++;
119: vsize++;
120: /* Note that either operand (but not both operands) might now have
121: leading zero limbs. It matters only that U is unnormalized if
122: vsize is now zero, and vice versa. And it is only in that case
123: that we have to adjust uexp. */
124: if (vsize == 0)
125: Lv0:
126: while (usize != 0 && up[usize - 1] == 0)
127: usize--, uexp--;
128: if (usize == 0)
129: Lu0:
130: while (vsize != 0 && vp[vsize - 1] == 0)
131: vsize--, uexp--;
132: }
133:
134: /* If U extends beyond PREC, ignore the part that does. */
135: if (usize > prec)
136: {
137: up += usize - prec;
138: usize = prec;
139: }
140:
141: /* If V extends beyond PREC, ignore the part that does.
142: Note that this may make vsize negative. */
143: if (vsize + ediff > prec)
144: {
145: vp += vsize + ediff - prec;
146: vsize = prec - ediff;
147: }
148:
149: /* Allocate temp space for the result. Allocate
150: just vsize + ediff later??? */
151: tp = (mp_ptr) TMP_ALLOC (prec * BYTES_PER_MP_LIMB);
152:
153: if (ediff >= prec)
154: {
155: /* V completely cancelled. */
156: if (tp != up)
157: MPN_COPY (rp, up, usize);
158: rsize = usize;
159: }
160: else
161: {
162: /* Locate the least significant non-zero limb in (the needed
163: parts of) U and V, to simplify the code below. */
164: for (;;)
165: {
166: if (vsize == 0)
167: {
168: MPN_COPY (rp, up, usize);
169: rsize = usize;
170: goto done;
171: }
172: if (vp[0] != 0)
173: break;
174: vp++, vsize--;
175: }
176: for (;;)
177: {
178: if (usize == 0)
179: {
180: MPN_COPY (rp, vp, vsize);
181: rsize = vsize;
182: negate ^= 1;
183: goto done;
184: }
185: if (up[0] != 0)
186: break;
187: up++, usize--;
188: }
189:
190: /* uuuu | uuuu | uuuu | uuuu | uuuu */
191: /* vvvvvvv | vv | vvvvv | v | vv */
192:
193: if (usize > ediff)
194: {
195: /* U and V partially overlaps. */
196: if (ediff == 0)
197: {
198: /* Have to compare the leading limbs of u and v
199: to determine whether to compute u - v or v - u. */
200: if (usize > vsize)
201: {
202: /* uuuu */
203: /* vv */
204: int cmp;
205: cmp = mpn_cmp (up + usize - vsize, vp, vsize);
206: if (cmp >= 0)
207: {
208: mp_size_t size;
209: size = usize - vsize;
210: MPN_COPY (tp, up, size);
211: mpn_sub_n (tp + size, up + size, vp, vsize);
212: rsize = usize;
213: }
214: else
215: {
216: /* vv */ /* Swap U and V. */
217: /* uuuu */
218: mp_size_t size, i;
219: size = usize - vsize;
220: tp[0] = -up[0];
221: for (i = 1; i < size; i++)
222: tp[i] = ~up[i];
223: mpn_sub_n (tp + size, vp, up + size, vsize);
224: mpn_sub_1 (tp + size, tp + size, vsize, (mp_limb_t) 1);
225: negate ^= 1;
226: rsize = usize;
227: }
228: }
229: else if (usize < vsize)
230: {
231: /* uuuu */
232: /* vvvvvvv */
233: int cmp;
234: cmp = mpn_cmp (up, vp + vsize - usize, usize);
235: if (cmp > 0)
236: {
237: mp_size_t size, i;
238: size = vsize - usize;
239: tp[0] = -vp[0];
240: for (i = 1; i < size; i++)
241: tp[i] = ~vp[i];
242: mpn_sub_n (tp + size, up, vp + size, usize);
243: mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
244: rsize = vsize;
245: }
246: else
247: {
248: /* vvvvvvv */ /* Swap U and V. */
249: /* uuuu */
250: /* This is the only place we can get 0.0. */
251: mp_size_t size;
252: size = vsize - usize;
253: MPN_COPY (tp, vp, size);
254: mpn_sub_n (tp + size, vp + size, up, usize);
255: negate ^= 1;
256: rsize = vsize;
257: }
258: }
259: else
260: {
261: /* uuuu */
262: /* vvvv */
263: int cmp;
264: cmp = mpn_cmp (up, vp + vsize - usize, usize);
265: if (cmp > 0)
266: {
267: mpn_sub_n (tp, up, vp, usize);
268: rsize = usize;
269: }
270: else
271: {
272: mpn_sub_n (tp, vp, up, usize);
273: negate ^= 1;
274: rsize = usize;
275: /* can give zero */
276: }
277: }
278: }
279: else
280: {
281: if (vsize + ediff <= usize)
282: {
283: /* uuuu */
284: /* v */
285: mp_size_t size;
286: size = usize - ediff - vsize;
287: MPN_COPY (tp, up, size);
288: mpn_sub (tp + size, up + size, usize - size, vp, vsize);
289: rsize = usize;
290: }
291: else
292: {
293: /* uuuu */
294: /* vvvvv */
295: mp_size_t size, i;
296: size = vsize + ediff - usize;
297: tp[0] = -vp[0];
298: for (i = 1; i < size; i++)
299: tp[i] = ~vp[i];
300: mpn_sub (tp + size, up, usize, vp + size, usize - ediff);
301: mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1);
302: rsize = vsize + ediff;
303: }
304: }
305: }
306: else
307: {
308: /* uuuu */
309: /* vv */
310: mp_size_t size, i;
311: size = vsize + ediff - usize;
312: tp[0] = -vp[0];
313: for (i = 1; i < vsize; i++)
314: tp[i] = ~vp[i];
315: for (i = vsize; i < size; i++)
316: tp[i] = ~(mp_limb_t) 0;
317: mpn_sub_1 (tp + size, up, usize, (mp_limb_t) 1);
318: rsize = size + usize;
319: }
320:
321: /* Full normalize. Optimize later. */
322: while (rsize != 0 && tp[rsize - 1] == 0)
323: {
324: rsize--;
325: uexp--;
326: }
327: MPN_COPY (rp, tp, rsize);
328: }
329:
330: done:
331: r->_mp_size = negate ? -rsize : rsize;
332: r->_mp_exp = uexp;
333: TMP_FREE (marker);
334: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>