summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mpf/set_str.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/mpf/set_str.c b/mpf/set_str.c
index 4dd18d8f3..c7bfe0b22 100644
--- a/mpf/set_str.c
+++ b/mpf/set_str.c
@@ -2,8 +2,8 @@
in base BASE to a float in dest. If BASE is zero, the leading characters
of STRING is used to figure out the base.
-Copyright 1993-1997, 2000-2003, 2005, 2007, 2008, 2011, 2013 Free Software
-Foundation, Inc.
+Copyright 1993-1997, 2000-2003, 2005, 2007, 2008, 2011, 2013, 2019 Free
+Software Foundation, Inc.
This file is part of the GNU MP Library.
@@ -126,12 +126,15 @@ mpf_set_str (mpf_ptr x, const char *str, int base)
size_t i, j;
int c;
int negative;
- char *dotpos = 0;
+ char *dotpos;
const char *expptr;
int exp_base;
const char *point = GMP_DECIMAL_POINT;
size_t pointlen = strlen (point);
const unsigned char *digit_value;
+ int incr;
+ size_t n_zeros_skipped;
+
TMP_DECL;
c = (unsigned char) *str;
@@ -198,6 +201,10 @@ mpf_set_str (mpf_ptr x, const char *str, int base)
TMP_MARK;
s = begs = (char *) TMP_ALLOC (str_size + 1);
+ incr = 0;
+ n_zeros_skipped = 0;
+ dotpos = NULL;
+
/* Loop through mantissa, converting it from ASCII to raw byte values. */
for (i = 0; i < str_size; i++)
{
@@ -230,7 +237,13 @@ mpf_set_str (mpf_ptr x, const char *str, int base)
TMP_FREE;
return -1;
}
- *s++ = dig;
+ *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 = (unsigned char) *++str;
@@ -251,19 +264,14 @@ mpf_set_str (mpf_ptr x, const char *str, int base)
#if 0
size_t n_chars_needed;
- /* This breaks things like 0.000...0001. To safely ignore superfluous
- digits, we need to skip over leading zeros. */
+ /* 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
- LIMBS_PER_DIGIT_IN_BASE (ma, str_size, base);
- mp = TMP_ALLOC_LIMBS (ma);
- mn = mpn_set_str (mp, (unsigned char *) begs, str_size, base);
-
- if (mn == 0)
+ if (str_size == 0)
{
SIZ(x) = 0;
EXP(x) = 0;
@@ -271,6 +279,10 @@ mpf_set_str (mpf_ptr x, const char *str, int base)
return 0;
}
+ LIMBS_PER_DIGIT_IN_BASE (ma, str_size, base);
+ mp = TMP_ALLOC_LIMBS (ma);
+ mn = mpn_set_str (mp, (unsigned char *) begs, str_size, base);
+
madj = 0;
/* Ignore excess limbs in MP,MSIZE. */
if (mn > prec)
@@ -310,7 +322,7 @@ mpf_set_str (mpf_ptr x, const char *str, int base)
else
exp_in_base = 0;
if (dotpos != 0)
- exp_in_base -= s - dotpos;
+ exp_in_base -= s - dotpos + n_zeros_skipped;
divflag = exp_in_base < 0;
exp_in_base = ABS (exp_in_base);