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-1997, 2000-2003, 2005, 2007, 2008, 2011, 2013 Free Software
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 either:
13 * the GNU Lesser General Public License as published by the Free
14 Software Foundation; either version 3 of the License, or (at your
15 option) any later version.
19 * the GNU General Public License as published by the Free Software
20 Foundation; either version 2 of the License, or (at your option) any
23 or both in parallel, as here.
25 The GNU MP Library is distributed in the hope that it will be useful, but
26 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
27 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
30 You should have received copies of the GNU General Public License and the
31 GNU Lesser General Public License along with the GNU MP Library. If not,
32 see https://www.gnu.org/licenses/. */
35 This still needs work, as suggested by some FIXME comments.
36 1. Don't depend on superfluous mantissa digits.
37 2. Allocate temp space more cleverly.
38 3. Use mpn_div_q instead of mpn_lshift+mpn_divrem.
41 #define _GNU_SOURCE /* for DECIMAL_POINT in langinfo.h */
50 #include <langinfo.h> /* for nl_langinfo */
54 #include <locale.h> /* for localeconv */
62 #define digit_value_tab __gmp_digit_value_tab
64 /* Compute base^exp and return the most significant prec limbs in rp[].
65 Put the count of omitted low limbs in *ign.
66 Return the actual size (which might be less than prec). */
68 mpn_pow_1_highpart (mp_ptr rp
, mp_size_t
*ignp
,
69 mp_limb_t base
, mp_exp_t exp
,
70 mp_size_t prec
, mp_ptr tp
)
72 mp_size_t ign
; /* counts number of ignored low limbs in r */
73 mp_size_t off
; /* keeps track of offset where value starts */
74 mp_ptr passed_rp
= rp
;
83 count_leading_zeros (cnt
, exp
);
84 for (i
= GMP_LIMB_BITS
- cnt
- 2; i
>= 0; i
--)
86 mpn_sqr (tp
, rp
+ off
, rn
);
88 rn
-= tp
[rn
- 1] == 0;
100 if (((exp
>> i
) & 1) != 0)
103 cy
= mpn_mul_1 (rp
, rp
+ off
, rn
, base
);
117 MPN_COPY_INCR (passed_rp
, rp
+ off
, rn
);
123 mpf_set_str (mpf_ptr x
, const char *str
, int base
)
133 const char *point
= GMP_DECIMAL_POINT
;
134 size_t pointlen
= strlen (point
);
135 const unsigned char *digit_value
;
138 c
= (unsigned char) *str
;
140 /* Skip whitespace. */
142 c
= (unsigned char) *++str
;
148 c
= (unsigned char) *++str
;
151 /* Default base to decimal. */
163 digit_value
= digit_value_tab
;
166 /* For bases > 36, use the collating sequence
167 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz. */
170 return -1; /* too large base */
173 /* Require at least one digit, possibly after an initial decimal point. */
174 if (digit_value
[c
] >= base
)
176 /* not a digit, must be a decimal point */
177 for (i
= 0; i
< pointlen
; i
++)
178 if (str
[i
] != point
[i
])
180 if (digit_value
[(unsigned char) str
[pointlen
]] >= base
)
184 /* Locate exponent part of the input. Look from the right of the string,
185 since the exponent is usually a lot shorter than the mantissa. */
187 str_size
= strlen (str
);
188 for (i
= str_size
- 1; i
> 0; i
--)
190 c
= (unsigned char) str
[i
];
191 if (c
== '@' || (base
<= 10 && (c
== 'e' || c
== 'E')))
193 expptr
= str
+ i
+ 1;
200 s
= begs
= (char *) TMP_ALLOC (str_size
+ 1);
202 /* Loop through mantissa, converting it from ASCII to raw byte values. */
203 for (i
= 0; i
< str_size
; i
++)
205 c
= (unsigned char) *str
;
210 for (j
= 0; j
< pointlen
; j
++)
211 if (str
[j
] != point
[j
])
217 /* already saw a decimal point, another is invalid */
228 dig
= digit_value
[c
];
237 c
= (unsigned char) *++str
;
244 mp_size_t ra
, ma
, rn
, mn
;
247 mp_exp_t exp_in_limbs
;
248 mp_size_t prec
= PREC(x
) + 1;
250 mp_size_t madj
, radj
;
253 size_t n_chars_needed
;
255 /* This breaks things like 0.000...0001. To safely ignore superfluous
256 digits, we need to skip over leading zeros. */
257 /* Just consider the relevant leading digits of the mantissa. */
258 LIMBS_PER_DIGIT_IN_BASE (n_chars_needed
, prec
, base
);
259 if (str_size
> n_chars_needed
)
260 str_size
= n_chars_needed
;
263 LIMBS_PER_DIGIT_IN_BASE (ma
, str_size
, base
);
264 mp
= TMP_ALLOC_LIMBS (ma
);
265 mn
= mpn_set_str (mp
, (unsigned char *) begs
, str_size
, base
);
276 /* Ignore excess limbs in MP,MSIZE. */
286 /* Scan and convert the exponent, in base exp_base. */
287 long dig
, minus
, plusminus
;
288 c
= (unsigned char) *expptr
;
289 minus
= -(long) (c
== '-');
290 plusminus
= minus
| -(long) (c
== '+');
291 expptr
-= plusminus
; /* conditional increment */
292 c
= (unsigned char) *expptr
++;
293 dig
= digit_value
[c
];
300 c
= (unsigned char) *expptr
++;
301 dig
= digit_value
[c
];
302 while (dig
< exp_base
)
304 exp_in_base
= exp_in_base
* exp_base
;
306 c
= (unsigned char) *expptr
++;
307 dig
= digit_value
[c
];
309 exp_in_base
= (exp_in_base
^ minus
) - minus
; /* conditional negation */
314 exp_in_base
-= s
- dotpos
;
315 divflag
= exp_in_base
< 0;
316 exp_in_base
= ABS (exp_in_base
);
318 if (exp_in_base
== 0)
320 MPN_COPY (PTR(x
), mp
, mn
);
321 SIZ(x
) = negative
? -mn
: mn
;
328 rp
= TMP_ALLOC_LIMBS (ra
);
329 tp
= TMP_ALLOC_LIMBS (ra
);
330 rn
= mpn_pow_1_highpart (rp
, &radj
, (mp_limb_t
) base
, exp_in_base
, prec
, tp
);
335 /* FIXME: Should use mpn_div_q here. */
337 mpn_div_q (tp
, mp
, mn
, rp
, rn
, scratch
);
344 /* Pad out MP,MSIZE for current divrem semantics. */
345 mp_ptr tmp
= TMP_ALLOC_LIMBS (rn
+ 1);
346 MPN_ZERO (tmp
, rn
- mn
);
347 MPN_COPY (tmp
+ rn
- mn
, mp
, mn
);
352 if ((rp
[rn
- 1] & GMP_NUMB_HIGHBIT
) == 0)
355 count_leading_zeros (cnt
, rp
[rn
- 1]);
356 cnt
-= GMP_NAIL_BITS
;
357 mpn_lshift (rp
, rp
, rn
, cnt
);
358 cy
= mpn_lshift (mp
, mp
, mn
, cnt
);
363 qp
= TMP_ALLOC_LIMBS (prec
+ 1);
364 qlimb
= mpn_divrem (qp
, prec
- (mn
- rn
), mp
, mn
, rp
, rn
);
366 exp_in_limbs
= qlimb
+ (mn
- rn
) + (madj
- radj
);
371 /* Skip the least significant limb not to overrun the destination
379 tp
= TMP_ALLOC_LIMBS (rn
+ mn
);
381 mpn_mul (tp
, rp
, rn
, mp
, mn
);
383 mpn_mul (tp
, mp
, mn
, rp
, rn
);
385 rn
-= tp
[rn
- 1] == 0;
386 exp_in_limbs
= rn
+ madj
+ radj
;
396 MPN_COPY (PTR(x
), tp
, rn
);
397 SIZ(x
) = negative
? -rn
: rn
;
398 EXP(x
) = exp_in_limbs
;