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.
5 Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
7 This file is part of the GNU MP Library.
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.
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.
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. */
30 long int strtol _PROTO ((const char *, char **ptr, int));
33 digit_value_in_base (c, base)
55 mpf_set_str (mpf_ptr x, const char *str, int base)
57 mpf_set_str (x, str, base)
71 int decimal_exponent_flag;
78 /* Skip whitespace. */
89 decimal_exponent_flag = base < 0;
92 if (digit_value_in_base (c, base == 0 ? 10 : base) < 0)
93 return -1; /* error if no digits */
95 /* If BASE is 0, try to find out the base by looking at the initial
105 if (c == 'x' || c == 'X')
112 str_size = strlen (str);
113 for (i = 0; i < str_size; i++)
116 if (c == '@' || (base <= 10 && (c == 'e' || c == 'E')))
125 s = begs = (char *) TMP_ALLOC (str_size + 1);
127 for (i = 0; i < str_size; i++)
145 dig = digit_value_in_base (c, base);
159 xsize = str_size / __mp_bases[base].chars_per_limb + 2;
162 mp_size_t rsize, msize;
164 mp_ptr mp, xp, tp, rp;
166 mp_exp_t exp_in_limbs;
167 mp_size_t prec = x->_mp_prec;
171 mp = (mp_ptr) TMP_ALLOC (xsize * BYTES_PER_MP_LIMB);
172 msize = mpn_set_str (mp, (unsigned char *) begs, str_size, base);
183 exp_in_base = strtol (str + 1, (char **) 0,
184 decimal_exponent_flag ? 10 : base);
188 exp_in_base -= s - dotpos;
189 divflag = exp_in_base < 0;
190 exp_in_base = ABS (exp_in_base);
192 if (exp_in_base == 0)
194 MPN_COPY (x->_mp_d, mp, msize);
195 x->_mp_size = negative ? -msize : msize;
202 rsize = (((mp_size_t) (exp_in_base / __mp_bases[base].chars_per_bit_exactly))
203 / BITS_PER_MP_LIMB + 3);
205 count_leading_zeros (cnt, (mp_limb_t) base);
206 rsize = exp_in_base - cnt * exp_in_base / BITS_PER_MP_LIMB + 1;
208 rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
209 tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB);
214 count_leading_zeros (cnt, exp_in_base);
216 for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--)
218 mpn_mul_n (tp, rp, rp, rsize);
220 rsize -= tp[rsize - 1] == 0;
221 xp = tp; tp = rp; rp = xp;
223 if (((exp_in_base >> i) & 1) != 0)
225 cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base);
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);
257 xxx += rsize - msize;
260 count_leading_zeros (cnt, rp[rsize - 1]);
263 mpn_lshift (rp, rp, rsize, cnt);
264 cy = mpn_lshift (mp, mp, msize, cnt);
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);
273 rsize = prec + qflag;
274 exp_in_limbs = rsize - xtra - xxx;
278 tp = (mp_ptr) TMP_ALLOC ((rsize + msize) * BYTES_PER_MP_LIMB);
280 mpn_mul (tp, rp, rsize, mp, msize);
282 mpn_mul (tp, mp, msize, rp, rsize);
284 rsize -= tp[rsize - 1] == 0;
285 exp_in_limbs = rsize + xxx;
296 MPN_COPY (x->_mp_d, tp, rsize);
297 x->_mp_size = negative ? -rsize : rsize;
298 x->_mp_exp = exp_in_limbs;