Annotation of OpenXM/src/kan96xx/gmp-2.0.2-ssh-2/mpf/set_str.c, Revision 1.1.1.1
1.1 takayama 1: /* mpf_set_str (dest, string, base) -- Convert the string STRING
2: in base BASE to a float in dest. If BASE is zero, the leading characters
3: of STRING is used to figure out the base.
4:
5: Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
6:
7: This file is part of the GNU MP Library.
8:
9: The GNU MP Library is free software; you can redistribute it and/or modify
10: it under the terms of the GNU Library General Public License as published by
11: the Free Software Foundation; either version 2 of the License, or (at your
12: option) any later version.
13:
14: The GNU MP Library is distributed in the hope that it will be useful, but
15: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
17: License for more details.
18:
19: You should have received a copy of the GNU Library General Public License
20: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
21: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22: MA 02111-1307, USA. */
23:
24: #include <string.h>
25: #include <ctype.h>
26: #include "gmp.h"
27: #include "gmp-impl.h"
28: #include "longlong.h"
29:
30: long int strtol _PROTO ((const char *, char **ptr, int));
31:
32: static int
33: digit_value_in_base (c, base)
34: int c;
35: int base;
36: {
37: int digit;
38:
39: if (isdigit (c))
40: digit = c - '0';
41: else if (islower (c))
42: digit = c - 'a' + 10;
43: else if (isupper (c))
44: digit = c - 'A' + 10;
45: else
46: return -1;
47:
48: if (digit < base)
49: return digit;
50: return -1;
51: }
52:
53: int
54: #if __STDC__
55: mpf_set_str (mpf_ptr x, const char *str, int base)
56: #else
57: mpf_set_str (x, str, base)
58: mpf_ptr x;
59: const char *str;
60: int base;
61: #endif
62: {
63: size_t str_size;
64: char *s, *begs;
65: size_t i;
66: mp_size_t xsize;
67: int c;
68: int negative;
69: char *dotpos = 0;
70: int expflag;
71: int decimal_exponent_flag;
72: TMP_DECL (marker);
73:
74: TMP_MARK (marker);
75:
76: c = *str;
77:
78: /* Skip whitespace. */
79: while (isspace (c))
80: c = *++str;
81:
82: negative = 0;
83: if (c == '-')
84: {
85: negative = 1;
86: c = *++str;
87: }
88:
89: decimal_exponent_flag = base < 0;
90: base = ABS (base);
91:
92: if (digit_value_in_base (c, base == 0 ? 10 : base) < 0)
93: return -1; /* error if no digits */
94:
95: /* If BASE is 0, try to find out the base by looking at the initial
96: characters. */
97: if (base == 0)
98: {
99: base = 10;
100: #if 0
101: if (c == '0')
102: {
103: base = 8;
104: c = *++str;
105: if (c == 'x' || c == 'X')
106: base = 16;
107: }
108: #endif
109: }
110:
111: expflag = 0;
112: str_size = strlen (str);
113: for (i = 0; i < str_size; i++)
114: {
115: c = str[i];
116: if (c == '@' || (base <= 10 && (c == 'e' || c == 'E')))
117: {
118: expflag = 1;
119: str_size = i;
120: break;
121: }
122:
123: }
124:
125: s = begs = (char *) TMP_ALLOC (str_size + 1);
126:
127: for (i = 0; i < str_size; i++)
128: {
129: c = *str;
130: if (!isspace (c))
131: {
132: int dig;
133:
134: if (c == '.')
135: {
136: if (dotpos != 0)
137: {
138: TMP_FREE (marker);
139: return -1;
140: }
141: dotpos = s;
142: }
143: else
144: {
145: dig = digit_value_in_base (c, base);
146: if (dig < 0)
147: {
148: TMP_FREE (marker);
149: return -1;
150: }
151: *s++ = dig;
152: }
153: }
154: c = *++str;
155: }
156:
157: str_size = s - begs;
158:
159: xsize = str_size / __mp_bases[base].chars_per_limb + 2;
160: {
161: long exp_in_base;
162: mp_size_t rsize, msize;
163: int cnt, i;
164: mp_ptr mp, xp, tp, rp;
165: mp_limb_t cy;
166: mp_exp_t exp_in_limbs;
167: mp_size_t prec = x->_mp_prec;
168: int divflag;
169: mp_size_t xxx = 0;
170:
171: mp = (mp_ptr) TMP_ALLOC (xsize * BYTES_PER_MP_LIMB);
172: msize = mpn_set_str (mp, (unsigned char *) begs, str_size, base);
173:
174: if (msize == 0)
175: {
176: x->_mp_size = 0;
177: x->_mp_exp = 0;
178: TMP_FREE (marker);
179: return 0;
180: }
181:
182: if (expflag != 0)
183: exp_in_base = strtol (str + 1, (char **) 0,
184: decimal_exponent_flag ? 10 : base);
185: else
186: exp_in_base = 0;
187: if (dotpos != 0)
188: exp_in_base -= s - dotpos;
189: divflag = exp_in_base < 0;
190: exp_in_base = ABS (exp_in_base);
191:
192: if (exp_in_base == 0)
193: {
194: MPN_COPY (x->_mp_d, mp, msize);
195: x->_mp_size = negative ? -msize : msize;
196: x->_mp_exp = msize;
197: TMP_FREE (marker);
198: return 0;
199: }
200:
201: #if 1
202: rsize = (((mp_size_t) (exp_in_base / __mp_bases[base].chars_per_bit_exactly))
203: / BITS_PER_MP_LIMB + 3);
204: #else
205: count_leading_zeros (cnt, (mp_limb_t) base);
206: rsize = exp_in_base - cnt * exp_in_base / BITS_PER_MP_LIMB + 1;
207: #endif
208: rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
209: tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
210:
211: rp[0] = base;
212: rsize = 1;
213:
214: count_leading_zeros (cnt, exp_in_base);
215:
216: for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)
217: {
218: mpn_mul_n (tp, rp, rp, rsize);
219: rsize = 2 * rsize;
220: rsize -= tp[rsize - 1] == 0;
221: xp = tp; tp = rp; rp = xp;
222:
223: if (((exp_in_base >> i) & 1) != 0)
224: {
225: cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base);
226: rp[rsize] = cy;
227: rsize += cy != 0;
228: }
229: }
230:
231: if (rsize > prec)
232: {
233: xxx += rsize - prec;
234: rp += rsize - prec;
235: rsize = prec;
236: }
237: #if 0
238: if (msize > prec)
239: {
240: xxx -= msize - prec;
241: mp += msize - prec;
242: msize = prec;
243: }
244: #endif
245: if (divflag)
246: {
247: mp_ptr qp;
248: mp_limb_t qflag;
249: mp_size_t xtra;
250: if (msize <= rsize)
251: {
252: /* Allocate extra limb for current divrem sematics. */
253: mp_ptr tmp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB);
254: MPN_ZERO (tmp, rsize - msize);
255: MPN_COPY (tmp + rsize - msize, mp, msize);
256: mp = tmp;
257: xxx += rsize - msize;
258: msize = rsize;
259: }
260: count_leading_zeros (cnt, rp[rsize - 1]);
261: if (cnt != 0)
262: {
263: mpn_lshift (rp, rp, rsize, cnt);
264: cy = mpn_lshift (mp, mp, msize, cnt);
265: if (cy)
266: mp[msize++] = cy;
267: }
268: qp = (mp_ptr) TMP_ALLOC ((prec + 1) * BYTES_PER_MP_LIMB);
269: xtra = prec - (msize - rsize);
270: qflag = mpn_divrem (qp, xtra, mp, msize, rp, rsize);
271: qp[prec] = qflag;
272: tp = qp;
273: rsize = prec + qflag;
274: exp_in_limbs = rsize - xtra - xxx;
275: }
276: else
277: {
278: tp = (mp_ptr) TMP_ALLOC ((rsize + msize) * BYTES_PER_MP_LIMB);
279: if (rsize > msize)
280: mpn_mul (tp, rp, rsize, mp, msize);
281: else
282: mpn_mul (tp, mp, msize, rp, rsize);
283: rsize += msize;
284: rsize -= tp[rsize - 1] == 0;
285: exp_in_limbs = rsize + xxx;
286:
287: if (rsize > prec)
288: {
289: xxx = rsize - prec;
290: tp += rsize - prec;
291: rsize = prec;
292: exp_in_limbs += 0;
293: }
294: }
295:
296: MPN_COPY (x->_mp_d, tp, rsize);
297: x->_mp_size = negative ? -rsize : rsize;
298: x->_mp_exp = exp_in_limbs;
299: TMP_FREE (marker);
300: return 0;
301: }
302: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>