/* mpf_set_str (dest, string, base) -- Convert the string STRING in base BASE to a float in dest. If BASE is zero, the leading characters of STRING is used to figure out the base.
The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
or
* the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
or both in parallel, as here.
The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received copies of the GNU General Public License and the GNU Lesser General Public License along with the GNU MP Library. If not,
see https://www.gnu.org/licenses/. */
/* This still needs work, as suggested by some FIXME comments. 1. Don't depend on superfluous mantissa digits. 2. Allocate temp space more cleverly. 3. Use mpn_div_q instead of mpn_lshift+mpn_divrem.
*/
#define _GNU_SOURCE /* for DECIMAL_POINT in langinfo.h */
#if HAVE_LANGINFO_H #include <langinfo.h> /* for nl_langinfo */ #endif
#if HAVE_LOCALE_H #include <locale.h> /* for localeconv */ #endif
#include"gmp-impl.h" #include"longlong.h"
#define digit_value_tab __gmp_digit_value_tab
/* Compute base^exp and return the most significant prec limbs in rp[]. Put the count of omitted low limbs in *ign.
Return the actual size (which might be less than prec). */ static mp_size_t
mpn_pow_1_highpart (mp_ptr rp, mp_size_t *ignp,
mp_limb_t base, mp_exp_t exp,
mp_size_t prec, mp_ptr tp)
{
mp_size_t ign; /* counts number of ignored low limbs in r */
mp_size_t off; /* keeps track of offset where value starts */
mp_ptr passed_rp = rp;
mp_size_t rn; int cnt; int i;
rp[0] = base;
rn = 1;
off = 0;
ign = 0;
count_leading_zeros (cnt, exp); for (i = GMP_LIMB_BITS - cnt - 2; i >= 0; i--)
{
mpn_sqr (tp, rp + off, rn);
rn = 2 * rn;
rn -= tp[rn - 1] == 0;
ign <<= 1;
off = 0; if (rn > prec)
{
ign += rn - prec;
off = rn - prec;
rn = prec;
}
MP_PTR_SWAP (rp, tp);
int
mpf_set_str (mpf_ptr x, constchar *str, int base)
{
size_t str_size; char *s, *begs;
size_t i, j; int c; int negative; char *dotpos; constchar *expptr; int exp_base; constchar *point = GMP_DECIMAL_POINT;
size_t pointlen = strlen (point); constunsignedchar *digit_value; int incr;
size_t n_zeros_skipped;
TMP_DECL;
c = (unsignedchar) *str;
/* Skip whitespace. */ while (isspace (c))
c = (unsignedchar) *++str;
negative = 0; if (c == '-')
{
negative = 1;
c = (unsignedchar) *++str;
}
/* Default base to decimal. */ if (base == 0)
base = 10;
exp_base = base;
if (base < 0)
{
exp_base = 10;
base = -base;
}
digit_value = digit_value_tab; if (base > 36)
{ /* For bases > 36, use the collating sequence
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz. */
digit_value += 208; if (base > 62) return -1; /* too large base */
}
/* Require at least one digit, possibly after an initial decimal point. */ if (digit_value[c] >= base)
{ /* not a digit, must be a decimal point */ for (i = 0; i < pointlen; i++) if (str[i] != point[i]) return -1; if (digit_value[(unsignedchar) str[pointlen]] >= base) return -1;
}
/* Locate exponent part of the input. Look from the right of the string,
since the exponent is usually a lot shorter than the mantissa. */
expptr = NULL;
str_size = strlen (str); for (i = str_size - 1; i > 0; i--)
{
c = (unsignedchar) str[i]; if (c == '@' || (base <= 10 && (c == 'e' || c == 'E')))
{
expptr = str + i + 1;
str_size = i; break;
}
}
/* Loop through mantissa, converting it from ASCII to raw byte values. */ for (i = 0; i < str_size; i++)
{
c = (unsignedchar) *str; if (!isspace (c))
{ int dig;
for (j = 0; j < pointlen; j++) if (str[j] != point[j]) goto not_point; if (1)
{ if (dotpos != 0)
{ /* already saw a decimal point, another is invalid */
TMP_FREE; return -1;
}
dotpos = s;
str += pointlen - 1;
i += pointlen - 1;
} else
{
not_point:
dig = digit_value[c]; if (dig >= base)
{
TMP_FREE; return -1;
}
*s = dig;
incr |= dig != 0;
s += incr; /* Increment after first non-0 digit seen. */ if (dotpos != NULL) /* Count skipped zeros between radix point and first non-0
digit. */
n_zeros_skipped += 1 - incr;
}
}
c = (unsignedchar) *++str;
}
str_size = s - begs;
{ long exp_in_base;
mp_size_t ra, ma, rn, mn; int cnt;
mp_ptr mp, tp, rp;
mp_exp_t exp_in_limbs;
mp_size_t prec = PREC(x) + 1; int divflag;
mp_size_t madj, radj;
#if 0
size_t n_chars_needed;
/* This needs careful testing. Leave disabled for now. */ /* Just consider the relevant leading digits of the mantissa. */
LIMBS_PER_DIGIT_IN_BASE (n_chars_needed, prec, base); if (str_size > n_chars_needed)
str_size = n_chars_needed; #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.