@@ -1340,16 +1340,17 @@ bigcomp(U *rv, const char *s0, BCinfo *bc)
13401340double
13411341_Py_dg_strtod (const char * s00 , char * * se )
13421342{
1343- int bb2 , bb5 , bbe , bd2 , bd5 , bbbits , bs2 , c , dp0 , dp1 , dplen , e , e1 , error ;
1343+ int bb2 , bb5 , bbe , bd2 , bd5 , bbbits , bs2 , c , e , e1 , error ;
13441344 int esign , i , j , k , nd , nd0 , nf , nz , nz0 , sign ;
13451345 const char * s , * s0 , * s1 ;
13461346 double aadj , aadj1 ;
13471347 U aadj2 , adj , rv , rv0 ;
1348- ULong y , z , L ;
1348+ ULong y , z , abse ;
1349+ Long L ;
13491350 BCinfo bc ;
13501351 Bigint * bb , * bb1 , * bd , * bd0 , * bs , * delta ;
13511352
1352- sign = nz0 = nz = dplen = 0 ;
1353+ sign = nz0 = nz = 0 ;
13531354 dval (& rv ) = 0. ;
13541355 for (s = s00 ;;s ++ ) switch (* s ) {
13551356 case '-' :
@@ -1381,18 +1382,11 @@ _Py_dg_strtod(const char *s00, char **se)
13811382 goto ret ;
13821383 }
13831384 s0 = s ;
1384- y = z = 0 ;
13851385 for (nd = nf = 0 ; (c = * s ) >= '0' && c <= '9' ; nd ++ , s ++ )
1386- if (nd < 9 )
1387- y = 10 * y + c - '0' ;
1388- else if (nd < 16 )
1389- z = 10 * z + c - '0' ;
1386+ ;
13901387 nd0 = nd ;
1391- dp0 = dp1 = s - s0 ;
13921388 if (c == '.' ) {
13931389 c = * ++ s ;
1394- dp1 = s - s0 ;
1395- dplen = 1 ;
13961390 if (!nd ) {
13971391 for (; c == '0' ; c = * ++ s )
13981392 nz ++ ;
@@ -1409,15 +1403,7 @@ _Py_dg_strtod(const char *s00, char **se)
14091403 nz ++ ;
14101404 if (c -= '0' ) {
14111405 nf += nz ;
1412- for (i = 1 ; i < nz ; i ++ )
1413- if (nd ++ < 9 )
1414- y *= 10 ;
1415- else if (nd <= DBL_DIG + 1 )
1416- z *= 10 ;
1417- if (nd ++ < 9 )
1418- y = 10 * y + c ;
1419- else if (nd <= DBL_DIG + 1 )
1420- z = 10 * z + c ;
1406+ nd += nz ;
14211407 nz = 0 ;
14221408 }
14231409 }
@@ -1440,17 +1426,17 @@ _Py_dg_strtod(const char *s00, char **se)
14401426 while (c == '0' )
14411427 c = * ++ s ;
14421428 if (c > '0' && c <= '9' ) {
1443- L = c - '0' ;
1429+ abse = c - '0' ;
14441430 s1 = s ;
14451431 while ((c = * ++ s ) >= '0' && c <= '9' )
1446- L = 10 * L + c - '0' ;
1447- if (s - s1 > 8 || L > MAX_ABS_EXP )
1432+ abse = 10 * abse + c - '0' ;
1433+ if (s - s1 > 8 || abse > MAX_ABS_EXP )
14481434 /* Avoid confusion from exponents
14491435 * so large that e might overflow.
14501436 */
14511437 e = (int )MAX_ABS_EXP ; /* safe for 16 bit ints */
14521438 else
1453- e = (int )L ;
1439+ e = (int )abse ;
14541440 if (esign )
14551441 e = - e ;
14561442 }
@@ -1468,15 +1454,78 @@ _Py_dg_strtod(const char *s00, char **se)
14681454 }
14691455 goto ret ;
14701456 }
1471- bc .e0 = e1 = e -= nf ;
1457+ e -= nf ;
1458+ if (!nd0 )
1459+ nd0 = nd ;
1460+
1461+ /* strip trailing zeros */
1462+ for (i = nd ; i > 0 ; ) {
1463+ /* scan back until we hit a nonzero digit. significant digit 'i'
1464+ is s0[i] if i < nd0, s0[i+1] if i >= nd0. */
1465+ -- i ;
1466+ if (s0 [i < nd0 ? i : i + 1 ] != '0' ) {
1467+ ++ i ;
1468+ break ;
1469+ }
1470+ }
1471+ e += nd - i ;
1472+ nd = i ;
1473+ if (nd0 > nd )
1474+ nd0 = nd ;
14721475
14731476 /* Now we have nd0 digits, starting at s0, followed by a
14741477 * decimal point, followed by nd-nd0 digits. The number we're
14751478 * after is the integer represented by those digits times
14761479 * 10**e */
14771480
1478- if (!nd0 )
1479- nd0 = nd ;
1481+ bc .e0 = e1 = e ;
1482+
1483+ /* Summary of parsing results. The parsing stage gives values
1484+ * s0, nd0, nd, e, sign, where:
1485+ *
1486+ * - s0 points to the first significant digit of the input string s00;
1487+ *
1488+ * - nd is the total number of significant digits (here, and
1489+ * below, 'significant digits' means the set of digits of the
1490+ * significand of the input that remain after ignoring leading
1491+ * and trailing zeros.
1492+ *
1493+ * - nd0 indicates the position of the decimal point (if
1494+ * present): so the nd significant digits are in s0[0:nd0] and
1495+ * s0[nd0+1:nd+1] using the usual Python half-open slice
1496+ * notation. (If nd0 < nd, then s0[nd0] necessarily contains
1497+ * a '.' character; if nd0 == nd, then it could be anything.)
1498+ *
1499+ * - e is the adjusted exponent: the absolute value of the number
1500+ * represented by the original input string is n * 10**e, where
1501+ * n is the integer represented by the concatenation of
1502+ * s0[0:nd0] and s0[nd0+1:nd+1]
1503+ *
1504+ * - sign gives the sign of the input: 1 for negative, 0 for positive
1505+ *
1506+ * - the first and last significant digits are nonzero
1507+ */
1508+
1509+ /* put first DBL_DIG+1 digits into integer y and z.
1510+ *
1511+ * - y contains the value represented by the first min(9, nd)
1512+ * significant digits
1513+ *
1514+ * - if nd > 9, z contains the value represented by significant digits
1515+ * with indices in [9, min(16, nd)). So y * 10**(min(16, nd) - 9) + z
1516+ * gives the value represented by the first min(16, nd) sig. digits.
1517+ */
1518+
1519+ y = z = 0 ;
1520+ for (i = 0 ; i < nd ; i ++ ) {
1521+ if (i < 9 )
1522+ y = 10 * y + s0 [i < nd0 ? i : i + 1 ] - '0' ;
1523+ else if (i < DBL_DIG + 1 )
1524+ z = 10 * z + s0 [i < nd0 ? i : i + 1 ] - '0' ;
1525+ else
1526+ break ;
1527+ }
1528+
14801529 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1 ;
14811530 dval (& rv ) = y ;
14821531 if (k > 9 ) {
@@ -1593,15 +1642,18 @@ _Py_dg_strtod(const char *s00, char **se)
15931642 /* ASSERT(STRTOD_DIGLIM >= 18); 18 == one more than the */
15941643 /* minimum number of decimal digits to distinguish double values */
15951644 /* in IEEE arithmetic. */
1596- i = j = 18 ;
1597- if (i > nd0 )
1598- j += dplen ;
1599- for (;;) {
1600- if (-- j <= dp1 && j >= dp0 )
1601- j = dp0 - 1 ;
1602- if (s0 [j ] != '0' )
1603- break ;
1645+
1646+ /* Truncate input to 18 significant digits, then discard any trailing
1647+ zeros on the result by updating nd, nd0, e and y suitably. (There's
1648+ no need to update z; it's not reused beyond this point.) */
1649+ for (i = 18 ; i > 0 ; ) {
1650+ /* scan back until we hit a nonzero digit. significant digit 'i'
1651+ is s0[i] if i < nd0, s0[i+1] if i >= nd0. */
16041652 -- i ;
1653+ if (s0 [i < nd0 ? i : i + 1 ] != '0' ) {
1654+ ++ i ;
1655+ break ;
1656+ }
16051657 }
16061658 e += nd - i ;
16071659 nd = i ;
@@ -1611,8 +1663,8 @@ _Py_dg_strtod(const char *s00, char **se)
16111663 y = 0 ;
16121664 for (i = 0 ; i < nd0 ; ++ i )
16131665 y = 10 * y + s0 [i ] - '0' ;
1614- for (j = dp1 ; i < nd ; ++ i )
1615- y = 10 * y + s0 [j ++ ] - '0' ;
1666+ for (; i < nd ; ++ i )
1667+ y = 10 * y + s0 [i + 1 ] - '0' ;
16161668 }
16171669 }
16181670 bd0 = s2b (s0 , nd0 , nd , y );
0 commit comments