version 1.1.1.1, 2000/01/10 15:35:22 |
version 1.1.1.2, 2000/09/09 14:13:08 |
|
|
in base BASE to a float in dest. If BASE is zero, the leading characters |
in base BASE to a float in dest. If BASE is zero, the leading characters |
of STRING is used to figure out the base. |
of STRING is used to figure out the base. |
|
|
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. |
Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000 Free Software Foundation, |
|
Inc. |
|
|
This file is part of the GNU MP Library. |
This file is part of the GNU MP Library. |
|
|
The GNU MP Library is free software; you can redistribute it and/or modify |
The GNU MP Library is free software; you can redistribute it and/or modify |
it under the terms of the GNU Library General Public License as published by |
it under the terms of the GNU Lesser General Public License as published by |
the Free Software Foundation; either version 2 of the License, or (at your |
the Free Software Foundation; either version 2.1 of the License, or (at your |
option) any later version. |
option) any later version. |
|
|
The GNU MP Library is distributed in the hope that it will be useful, but |
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 |
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
License for more details. |
License for more details. |
|
|
You should have received a copy of the GNU Library General Public License |
You should have received a copy of the GNU Lesser General Public License |
along with the GNU MP Library; see the file COPYING.LIB. If not, write to |
along with the GNU MP Library; see the file COPYING.LIB. If not, write to |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
MA 02111-1307, USA. */ |
MA 02111-1307, USA. */ |
Line 27 MA 02111-1307, USA. */ |
|
Line 28 MA 02111-1307, USA. */ |
|
#include "gmp-impl.h" |
#include "gmp-impl.h" |
#include "longlong.h" |
#include "longlong.h" |
|
|
|
|
long int strtol _PROTO ((const char *, char **ptr, int)); |
long int strtol _PROTO ((const char *, char **ptr, int)); |
|
|
static int |
static int |
|
#if __STDC__ |
|
digit_value_in_base (int c, int base) |
|
#else |
digit_value_in_base (c, base) |
digit_value_in_base (c, base) |
int c; |
int c; |
int base; |
int base; |
|
#endif |
{ |
{ |
int digit; |
int digit; |
|
|
Line 89 mpf_set_str (x, str, base) |
|
Line 95 mpf_set_str (x, str, base) |
|
decimal_exponent_flag = base < 0; |
decimal_exponent_flag = base < 0; |
base = ABS (base); |
base = ABS (base); |
|
|
if (digit_value_in_base (c, base == 0 ? 10 : base) < 0) |
if (digit_value_in_base (c, base == 0 ? 10 : base) < 0 |
|
&& (c != '.' || digit_value_in_base (str[1], base == 0 ? 10 : base) < 0)) |
return -1; /* error if no digits */ |
return -1; /* error if no digits */ |
|
|
/* If BASE is 0, try to find out the base by looking at the initial |
/* If BASE is 0, try to find out the base by looking at the initial |
Line 101 mpf_set_str (x, str, base) |
|
Line 108 mpf_set_str (x, str, base) |
|
if (c == '0') |
if (c == '0') |
{ |
{ |
base = 8; |
base = 8; |
c = *++str; |
if (str[1] == 'x' || str[1] == 'X') |
if (c == 'x' || c == 'X') |
{ |
base = 16; |
base = 16; |
|
str += 2; |
|
c = *str; |
|
} |
} |
} |
#endif |
#endif |
} |
} |
Line 159 mpf_set_str (x, str, base) |
|
Line 169 mpf_set_str (x, str, base) |
|
xsize = str_size / __mp_bases[base].chars_per_limb + 2; |
xsize = str_size / __mp_bases[base].chars_per_limb + 2; |
{ |
{ |
long exp_in_base; |
long exp_in_base; |
mp_size_t rsize, msize; |
mp_size_t ralloc, rsize, msize; |
int cnt, i; |
int cnt, i; |
mp_ptr mp, xp, tp, rp; |
mp_ptr mp, tp, rp; |
mp_limb_t cy; |
|
mp_exp_t exp_in_limbs; |
mp_exp_t exp_in_limbs; |
mp_size_t prec = x->_mp_prec; |
mp_size_t prec = x->_mp_prec + 1; |
int divflag; |
int divflag; |
mp_size_t xxx = 0; |
mp_size_t madj, radj; |
|
|
mp = (mp_ptr) TMP_ALLOC (xsize * BYTES_PER_MP_LIMB); |
mp = (mp_ptr) TMP_ALLOC (xsize * BYTES_PER_MP_LIMB); |
msize = mpn_set_str (mp, (unsigned char *) begs, str_size, base); |
msize = mpn_set_str (mp, (unsigned char *) begs, str_size, base); |
Line 179 mpf_set_str (x, str, base) |
|
Line 188 mpf_set_str (x, str, base) |
|
return 0; |
return 0; |
} |
} |
|
|
|
madj = 0; |
|
/* Ignore excess limbs in MP,MSIZE. */ |
|
if (msize > prec) |
|
{ |
|
madj = msize - prec; |
|
mp += msize - prec; |
|
msize = prec; |
|
} |
|
|
if (expflag != 0) |
if (expflag != 0) |
exp_in_base = strtol (str + 1, (char **) 0, |
exp_in_base = strtol (str + 1, (char **) 0, |
decimal_exponent_flag ? 10 : base); |
decimal_exponent_flag ? 10 : base); |
Line 193 mpf_set_str (x, str, base) |
|
Line 211 mpf_set_str (x, str, base) |
|
{ |
{ |
MPN_COPY (x->_mp_d, mp, msize); |
MPN_COPY (x->_mp_d, mp, msize); |
x->_mp_size = negative ? -msize : msize; |
x->_mp_size = negative ? -msize : msize; |
x->_mp_exp = msize; |
x->_mp_exp = msize + madj; |
TMP_FREE (marker); |
TMP_FREE (marker); |
return 0; |
return 0; |
} |
} |
|
|
#if 1 |
radj = 0; /* counts number of ignored low limbs in r */ |
rsize = (((mp_size_t) (exp_in_base / __mp_bases[base].chars_per_bit_exactly)) |
|
/ BITS_PER_MP_LIMB + 3); |
|
#else |
|
count_leading_zeros (cnt, (mp_limb_t) base); |
|
rsize = exp_in_base - cnt * exp_in_base / BITS_PER_MP_LIMB + 1; |
|
#endif |
|
rp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); |
|
tp = (mp_ptr) TMP_ALLOC (rsize * BYTES_PER_MP_LIMB); |
|
|
|
|
ralloc = 2 * (prec + 1); |
|
rp = (mp_ptr) TMP_ALLOC (ralloc * BYTES_PER_MP_LIMB); |
|
tp = (mp_ptr) TMP_ALLOC (ralloc * BYTES_PER_MP_LIMB); |
|
|
rp[0] = base; |
rp[0] = base; |
rsize = 1; |
rsize = 1; |
|
|
count_leading_zeros (cnt, exp_in_base); |
count_leading_zeros (cnt, exp_in_base); |
|
|
for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--) |
for (i = BITS_PER_MP_LIMB - cnt - 2; i >= 0; i--) |
{ |
{ |
mpn_mul_n (tp, rp, rp, rsize); |
mpn_mul_n (tp, rp, rp, rsize); |
rsize = 2 * rsize; |
rsize = 2 * rsize; |
rsize -= tp[rsize - 1] == 0; |
rsize -= tp[rsize - 1] == 0; |
xp = tp; tp = rp; rp = xp; |
radj <<= 1; |
|
|
|
if (rsize > prec) |
|
{ |
|
radj += rsize - prec; |
|
MPN_COPY_INCR (rp, tp + rsize - prec, prec); |
|
rsize = prec; |
|
} |
|
else |
|
MP_PTR_SWAP (rp, tp); |
|
|
if (((exp_in_base >> i) & 1) != 0) |
if (((exp_in_base >> i) & 1) != 0) |
{ |
{ |
|
mp_limb_t cy; |
cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base); |
cy = mpn_mul_1 (rp, rp, rsize, (mp_limb_t) base); |
rp[rsize] = cy; |
rp[rsize] = cy; |
rsize += cy != 0; |
rsize += cy != 0; |
Line 230 mpf_set_str (x, str, base) |
|
Line 252 mpf_set_str (x, str, base) |
|
|
|
if (rsize > prec) |
if (rsize > prec) |
{ |
{ |
xxx += rsize - prec; |
radj += rsize - prec; |
rp += rsize - prec; |
rp += rsize - prec; |
rsize = prec; |
rsize = prec; |
} |
} |
#if 0 |
|
if (msize > prec) |
|
{ |
|
xxx -= msize - prec; |
|
mp += msize - prec; |
|
msize = prec; |
|
} |
|
#endif |
|
if (divflag) |
if (divflag) |
{ |
{ |
mp_ptr qp; |
mp_ptr qp; |
mp_limb_t qflag; |
mp_limb_t qlimb; |
mp_size_t xtra; |
if (msize < rsize) |
if (msize <= rsize) |
|
{ |
{ |
/* Allocate extra limb for current divrem sematics. */ |
/* Pad out MP,MSIZE for current divrem semantics. */ |
mp_ptr tmp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB); |
mp_ptr tmp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB); |
MPN_ZERO (tmp, rsize - msize); |
MPN_ZERO (tmp, rsize - msize); |
MPN_COPY (tmp + rsize - msize, mp, msize); |
MPN_COPY (tmp + rsize - msize, mp, msize); |
mp = tmp; |
mp = tmp; |
xxx += rsize - msize; |
madj -= rsize - msize; |
msize = rsize; |
msize = rsize; |
} |
} |
count_leading_zeros (cnt, rp[rsize - 1]); |
count_leading_zeros (cnt, rp[rsize - 1]); |
if (cnt != 0) |
if (cnt != 0) |
{ |
{ |
|
mp_limb_t cy; |
mpn_lshift (rp, rp, rsize, cnt); |
mpn_lshift (rp, rp, rsize, cnt); |
cy = mpn_lshift (mp, mp, msize, cnt); |
cy = mpn_lshift (mp, mp, msize, cnt); |
if (cy) |
if (cy) |
mp[msize++] = cy; |
mp[msize++] = cy; |
} |
} |
|
|
qp = (mp_ptr) TMP_ALLOC ((prec + 1) * BYTES_PER_MP_LIMB); |
qp = (mp_ptr) TMP_ALLOC ((prec + 1) * BYTES_PER_MP_LIMB); |
xtra = prec - (msize - rsize); |
qlimb = mpn_divrem (qp, prec - (msize - rsize), mp, msize, rp, rsize); |
qflag = mpn_divrem (qp, xtra, mp, msize, rp, rsize); |
|
qp[prec] = qflag; |
|
tp = qp; |
tp = qp; |
rsize = prec + qflag; |
exp_in_limbs = qlimb + (msize - rsize) + (madj - radj); |
exp_in_limbs = rsize - xtra - xxx; |
rsize = prec; |
|
if (qlimb != 0) |
|
{ |
|
tp[prec] = qlimb; |
|
/* Skip the least significant limb not to overrun the destination |
|
variable. */ |
|
tp++; |
|
} |
} |
} |
else |
else |
{ |
{ |
Line 282 mpf_set_str (x, str, base) |
|
Line 303 mpf_set_str (x, str, base) |
|
mpn_mul (tp, mp, msize, rp, rsize); |
mpn_mul (tp, mp, msize, rp, rsize); |
rsize += msize; |
rsize += msize; |
rsize -= tp[rsize - 1] == 0; |
rsize -= tp[rsize - 1] == 0; |
exp_in_limbs = rsize + xxx; |
exp_in_limbs = rsize + madj + radj; |
|
|
if (rsize > prec) |
if (rsize > prec) |
{ |
{ |
xxx = rsize - prec; |
|
tp += rsize - prec; |
tp += rsize - prec; |
rsize = prec; |
rsize = prec; |
exp_in_limbs += 0; |
exp_in_limbs += 0; |