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 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2002, 2003, 2005, 2007,
6 2008 Free Software Foundation, Inc.
8 This file is part of the GNU MP Library.
10 The GNU MP Library is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or (at your
13 option) any later version.
15 The GNU MP Library is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 License for more details.
20 You should have received a copy of the GNU Lesser General Public License
21 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
24 This still needs work, as suggested by some FIXME comments.
25 1. Don't depend on superfluous mantissa digits.
26 2. Allocate temp space more cleverly.
27 3. Use mpn_tdiv_qr instead of mpn_lshift+mpn_divrem.
30 #define _GNU_SOURCE /* for DECIMAL_POINT in langinfo.h */
39 #include <langinfo.h> /* for nl_langinfo */
43 #include <locale.h> /* for localeconv */
50 extern const unsigned char __gmp_digit_value_tab
[];
51 #define digit_value_tab __gmp_digit_value_tab
53 /* Compute base^exp and return the most significant prec limbs in rp[].
54 Put the count of omitted low limbs in *ign.
55 Return the actual size (which might be less than prec). */
57 mpn_pow_1_highpart (mp_ptr rp
, mp_size_t
*ignp
,
58 mp_limb_t base
, mp_exp_t exp
,
59 mp_size_t prec
, mp_ptr tp
)
61 mp_size_t ign
; /* counts number of ignored low limbs in r */
62 mp_size_t off
; /* keeps track of offset where value starts */
63 mp_ptr passed_rp
= rp
;
72 count_leading_zeros (cnt
, exp
);
73 for (i
= GMP_LIMB_BITS
- cnt
- 2; i
>= 0; i
--)
75 mpn_sqr (tp
, rp
+ off
, rn
);
77 rn
-= tp
[rn
- 1] == 0;
89 if (((exp
>> i
) & 1) != 0)
92 cy
= mpn_mul_1 (rp
, rp
+ off
, rn
, base
);
106 MPN_COPY_INCR (passed_rp
, rp
+ off
, rn
);
112 mpf_set_str (mpf_ptr x
, const char *str
, int base
)
122 const char *point
= GMP_DECIMAL_POINT
;
123 size_t pointlen
= strlen (point
);
124 const unsigned char *digit_value
;
127 c
= (unsigned char) *str
;
129 /* Skip whitespace. */
131 c
= (unsigned char) *++str
;
137 c
= (unsigned char) *++str
;
140 /* Default base to decimal. */
152 digit_value
= digit_value_tab
;
155 /* For bases > 36, use the collating sequence
156 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz. */
159 return -1; /* too large base */
162 /* Require at least one digit, possibly after an initial decimal point. */
163 if (digit_value
[c
] >= (base
== 0 ? 10 : base
))
165 /* not a digit, must be a decimal point */
166 for (i
= 0; i
< pointlen
; i
++)
167 if (str
[i
] != point
[i
])
169 if (digit_value
[(unsigned char) str
[pointlen
]] >= (base
== 0 ? 10 : base
))
173 /* Locate exponent part of the input. Look from the right of the string,
174 since the exponent is usually a lot shorter than the mantissa. */
176 str_size
= strlen (str
);
177 for (i
= str_size
- 1; i
> 0; i
--)
179 c
= (unsigned char) str
[i
];
180 if (c
== '@' || (base
<= 10 && (c
== 'e' || c
== 'E')))
182 expptr
= str
+ i
+ 1;
189 s
= begs
= (char *) TMP_ALLOC (str_size
+ 1);
191 /* Loop through mantissa, converting it from ASCII to raw byte values. */
192 for (i
= 0; i
< str_size
; i
++)
194 c
= (unsigned char) *str
;
199 for (j
= 0; j
< pointlen
; j
++)
200 if (str
[j
] != point
[j
])
206 /* already saw a decimal point, another is invalid */
217 dig
= digit_value
[c
];
226 c
= (unsigned char) *++str
;
233 mp_size_t ra
, ma
, rn
, mn
;
236 mp_exp_t exp_in_limbs
;
237 mp_size_t prec
= PREC(x
) + 1;
239 mp_size_t madj
, radj
;
242 size_t n_chars_needed
;
244 /* This breaks things like 0.000...0001. To safely ignore superfluous
245 digits, we need to skip over leading zeros. */
246 /* Just consider the relevant leading digits of the mantissa. */
247 n_chars_needed
= 2 + (size_t)
248 (((size_t) prec
* GMP_NUMB_BITS
) * mp_bases
[base
].chars_per_bit_exactly
);
249 if (str_size
> n_chars_needed
)
250 str_size
= n_chars_needed
;
254 (str_size
/ (GMP_NUMB_BITS
* mp_bases
[base
].chars_per_bit_exactly
));
255 mp
= TMP_ALLOC_LIMBS (ma
);
256 mn
= mpn_set_str (mp
, (unsigned char *) begs
, str_size
, base
);
267 /* Ignore excess limbs in MP,MSIZE. */
277 /* Scan and convert the exponent, in base exp_base. */
278 long dig
, minus
, plusminus
;
279 c
= (unsigned char) *expptr
;
280 minus
= -(long) (c
== '-');
281 plusminus
= minus
| -(long) (c
== '+');
282 expptr
-= plusminus
; /* conditional increment */
283 c
= (unsigned char) *expptr
++;
284 dig
= digit_value
[c
];
291 c
= (unsigned char) *expptr
++;
292 dig
= digit_value
[c
];
293 while (dig
< exp_base
)
295 exp_in_base
= exp_in_base
* exp_base
;
297 c
= (unsigned char) *expptr
++;
298 dig
= digit_value
[c
];
300 exp_in_base
= (exp_in_base
^ minus
) - minus
; /* conditional negation */
305 exp_in_base
-= s
- dotpos
;
306 divflag
= exp_in_base
< 0;
307 exp_in_base
= ABS (exp_in_base
);
309 if (exp_in_base
== 0)
311 MPN_COPY (PTR(x
), mp
, mn
);
312 SIZ(x
) = negative
? -mn
: mn
;
319 rp
= TMP_ALLOC_LIMBS (ra
);
320 tp
= TMP_ALLOC_LIMBS (ra
);
321 rn
= mpn_pow_1_highpart (rp
, &radj
, (mp_limb_t
) base
, exp_in_base
, prec
, tp
);
326 /* FIXME: Should use mpn_tdiv here. */
327 mpn_tdiv_qr (qp
, mp
, 0L, mp
, mn
, rp
, rn
);
333 /* Pad out MP,MSIZE for current divrem semantics. */
334 mp_ptr tmp
= TMP_ALLOC_LIMBS (rn
+ 1);
335 MPN_ZERO (tmp
, rn
- mn
);
336 MPN_COPY (tmp
+ rn
- mn
, mp
, mn
);
341 if ((rp
[rn
- 1] & GMP_NUMB_HIGHBIT
) == 0)
344 count_leading_zeros (cnt
, rp
[rn
- 1]);
345 cnt
-= GMP_NAIL_BITS
;
346 mpn_lshift (rp
, rp
, rn
, cnt
);
347 cy
= mpn_lshift (mp
, mp
, mn
, cnt
);
352 qp
= TMP_ALLOC_LIMBS (prec
+ 1);
353 qlimb
= mpn_divrem (qp
, prec
- (mn
- rn
), mp
, mn
, rp
, rn
);
355 exp_in_limbs
= qlimb
+ (mn
- rn
) + (madj
- radj
);
360 /* Skip the least significant limb not to overrun the destination
368 tp
= TMP_ALLOC_LIMBS (rn
+ mn
);
370 mpn_mul (tp
, rp
, rn
, mp
, mn
);
372 mpn_mul (tp
, mp
, mn
, rp
, rn
);
374 rn
-= tp
[rn
- 1] == 0;
375 exp_in_limbs
= rn
+ madj
+ radj
;
385 MPN_COPY (PTR(x
), tp
, rn
);
386 SIZ(x
) = negative
? -rn
: rn
;
387 EXP(x
) = exp_in_limbs
;