33#include <Python.h>
44#include "pycore_dtoa.h" // _Py_dg_strtod()
55#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
6+ #include "pycore_ryu.h" // _Py_ryu_dtoa()
67
78#include <locale.h> // localeconv()
89
@@ -942,19 +943,19 @@ static const char * const uc_float_strings[] = {
942943
943944 Arguments:
944945 d is the double to be converted
945- format_code is one of 'e', 'f', 'g', 'r'. 'e', 'f' and 'g'
946- correspond to '%e', '%f' and '%g'; 'r' corresponds to repr.
947- mode is one of '0', '2' or '3', and is completely determined by
948- format_code: 'e' and 'g' use mode 2; 'f' mode 3, 'r' mode 0.
946+ format_code is one of 'e', 'f', 'g'. 'e', 'f' and 'g'
947+ correspond to '%e', '%f' and '%g'. ('r' is handled separately
948+ by double_repr_buffered() below.)
949+ mode is one of '2' or '3', and is completely determined by
950+ format_code: 'e' and 'g' use mode 2; 'f' mode 3.
949951 precision is the desired precision
950952 always_add_sign is nonzero if a '+' sign should be included for positive
951953 numbers
952954 add_dot_0_if_integer is nonzero if integers in non-exponential form
953- should have ".0" added. Only applies to format codes 'r' and 'g'.
955+ should have ".0" added. Only applies to format code 'g'.
954956 use_alt_formatting is nonzero if alternative formatting should be
955- used. Only applies to format codes 'e', 'f' and 'g'. For code 'g',
956- at most one of use_alt_formatting and add_dot_0_if_integer should
957- be nonzero.
957+ used. For code 'g', at most one of use_alt_formatting and
958+ add_dot_0_if_integer should be nonzero.
958959 type, if non-NULL, will be set to one of these constants to identify
959960 the type of the 'd' argument:
960961 Py_DTST_FINITE
@@ -976,7 +977,7 @@ format_float_short(double d, char format_code,
976977 char * p = NULL ;
977978 Py_ssize_t bufsize = 0 ;
978979 char * digits , * digits_end ;
979- int decpt_as_int , sign , exp_len , exp = 0 , use_exp = 0 ;
980+ int decpt_as_int , sign , exp = 0 , use_exp = 0 ;
980981 Py_ssize_t decpt , digits_len , vdigits_start , vdigits_end ;
981982 _Py_SET_53BIT_PRECISION_HEADER ;
982983
@@ -1090,15 +1091,6 @@ format_float_short(double d, char format_code,
10901091 if (use_alt_formatting )
10911092 vdigits_end = precision ;
10921093 break ;
1093- case 'r' :
1094- /* convert to exponential format at 1e16. We used to convert
1095- at 1e17, but that gives odd-looking results for some values
1096- when a 16-digit 'shortest' repr is padded with bogus zeros.
1097- For example, repr(2e16+8) would give 20000000000000010.0;
1098- the true value is 20000000000000008.0. */
1099- if (decpt <= -4 || decpt > 16 )
1100- use_exp = 1 ;
1101- break ;
11021094 default :
11031095 PyErr_BadInternalCall ();
11041096 goto exit ;
@@ -1201,8 +1193,24 @@ format_float_short(double d, char format_code,
12011193 /* Now that we've done zero padding, add an exponent if needed. */
12021194 if (use_exp ) {
12031195 * p ++ = float_strings [OFS_E ][0 ];
1204- exp_len = sprintf (p , "%+.02d" , exp );
1205- p += exp_len ;
1196+ /* Emit a sign followed by at least two exponent digits. For
1197+ IEEE 754 doubles |exp| < 1000, so at most three digits. */
1198+ unsigned int uexp ;
1199+ if (exp < 0 ) {
1200+ * p ++ = '-' ;
1201+ uexp = (unsigned int )(- exp );
1202+ }
1203+ else {
1204+ * p ++ = '+' ;
1205+ uexp = (unsigned int )exp ;
1206+ }
1207+ assert (uexp < 1000 ); /* matches the bufsize computation above */
1208+ if (uexp >= 100 ) {
1209+ * p ++ = (char )('0' + uexp / 100 );
1210+ uexp %= 100 ;
1211+ }
1212+ * p ++ = (char )('0' + uexp / 10 );
1213+ * p ++ = (char )('0' + uexp % 10 );
12061214 }
12071215 exit :
12081216 if (buf ) {
@@ -1218,6 +1226,140 @@ format_float_short(double d, char format_code,
12181226}
12191227
12201228
1229+ /* Write the Python repr of a finite or non-finite double into the
1230+ caller-provided buffer. This is equivalent to PyOS_double_to_string
1231+ with format code 'r', but never allocates.
1232+
1233+ The 'r' formatting rules are simple enough to implement directly here
1234+ rather than going through format_float_short. */
1235+ static Py_ssize_t
1236+ double_repr_buffered (double val , char * buf , Py_ssize_t bufsize ,
1237+ int flags , int * type )
1238+ {
1239+ assert (bufsize >= _Py_DOUBLE_REPR_BUFSIZE );
1240+ (void )bufsize ;
1241+
1242+ char digits [_Py_RYU_DTOA_BUFSIZE ];
1243+ int decpt , sign ;
1244+ int digits_len = _Py_ryu_dtoa (val , digits , & decpt , & sign );
1245+
1246+ char * p = buf ;
1247+
1248+ if (!Py_ISDIGIT (digits [0 ])) {
1249+ int is_nan = (digits [0 ] == 'N' );
1250+ if (type ) {
1251+ * type = is_nan ? Py_DTST_NAN : Py_DTST_INFINITE ;
1252+ }
1253+ if (is_nan ) {
1254+ sign = 0 ;
1255+ }
1256+ if (sign ) {
1257+ * p ++ = '-' ;
1258+ }
1259+ else if (flags & Py_DTSF_SIGN ) {
1260+ * p ++ = '+' ;
1261+ }
1262+ memcpy (p , is_nan ? "nan" : "inf" , 3 );
1263+ p += 3 ;
1264+ * p = '\0' ;
1265+ return p - buf ;
1266+ }
1267+
1268+ if (type ) {
1269+ * type = Py_DTST_FINITE ;
1270+ }
1271+ if ((flags & Py_DTSF_NO_NEG_0 ) && sign
1272+ && digits_len == 1 && digits [0 ] == '0' )
1273+ {
1274+ sign = 0 ;
1275+ }
1276+ if (sign ) {
1277+ * p ++ = '-' ;
1278+ }
1279+ else if (flags & Py_DTSF_SIGN ) {
1280+ * p ++ = '+' ;
1281+ }
1282+
1283+ /* Convert to exponential format at 1e16. We used to convert
1284+ at 1e17, but that gives odd-looking results for some values
1285+ when a 16-digit 'shortest' repr is padded with bogus zeros.
1286+ For example, repr(2e16+8) would give 20000000000000010.0;
1287+ the true value is 20000000000000008.0. */
1288+ if (decpt <= -4 || decpt > 16 ) {
1289+ /* Exponential form: D.DDDe+NN */
1290+ * p ++ = digits [0 ];
1291+ if (digits_len > 1 ) {
1292+ * p ++ = '.' ;
1293+ memcpy (p , digits + 1 , (size_t )(digits_len - 1 ));
1294+ p += digits_len - 1 ;
1295+ }
1296+ else if (flags & Py_DTSF_ALT ) {
1297+ * p ++ = '.' ;
1298+ }
1299+ * p ++ = 'e' ;
1300+ int exp = decpt - 1 ;
1301+ unsigned int uexp ;
1302+ if (exp < 0 ) {
1303+ * p ++ = '-' ;
1304+ uexp = (unsigned int )(- exp );
1305+ }
1306+ else {
1307+ * p ++ = '+' ;
1308+ uexp = (unsigned int )exp ;
1309+ }
1310+ assert (uexp < 1000 );
1311+ if (uexp >= 100 ) {
1312+ * p ++ = (char )('0' + uexp / 100 );
1313+ uexp %= 100 ;
1314+ }
1315+ * p ++ = (char )('0' + uexp / 10 );
1316+ * p ++ = (char )('0' + uexp % 10 );
1317+ }
1318+ else if (decpt <= 0 ) {
1319+ /* 0.[000]DDD */
1320+ * p ++ = '0' ;
1321+ * p ++ = '.' ;
1322+ memset (p , '0' , (size_t )(- decpt ));
1323+ p += - decpt ;
1324+ memcpy (p , digits , (size_t )digits_len );
1325+ p += digits_len ;
1326+ }
1327+ else if (decpt < digits_len ) {
1328+ /* DD.DDD */
1329+ memcpy (p , digits , (size_t )decpt );
1330+ p += decpt ;
1331+ * p ++ = '.' ;
1332+ memcpy (p , digits + decpt , (size_t )(digits_len - decpt ));
1333+ p += digits_len - decpt ;
1334+ }
1335+ else {
1336+ /* DDD[000][.0] */
1337+ memcpy (p , digits , (size_t )digits_len );
1338+ p += digits_len ;
1339+ memset (p , '0' , (size_t )(decpt - digits_len ));
1340+ p += decpt - digits_len ;
1341+ if (flags & Py_DTSF_ADD_DOT_0 ) {
1342+ * p ++ = '.' ;
1343+ * p ++ = '0' ;
1344+ }
1345+ else if (flags & Py_DTSF_ALT ) {
1346+ * p ++ = '.' ;
1347+ }
1348+ }
1349+
1350+ * p = '\0' ;
1351+ assert (p - buf < _Py_DOUBLE_REPR_BUFSIZE );
1352+ return p - buf ;
1353+ }
1354+
1355+
1356+ Py_ssize_t
1357+ _Py_double_repr_buffered (double val , char * buf , Py_ssize_t bufsize , int flags )
1358+ {
1359+ return double_repr_buffered (val , buf , bufsize , flags , NULL );
1360+ }
1361+
1362+
12211363char * PyOS_double_to_string (double val ,
12221364 char format_code ,
12231365 int precision ,
@@ -1262,14 +1404,20 @@ char * PyOS_double_to_string(double val,
12621404 break ;
12631405
12641406 /* repr format */
1265- case 'r' :
1266- mode = 0 ;
1407+ case 'r' : {
12671408 /* Supplied precision is unused, must be 0. */
12681409 if (precision != 0 ) {
12691410 PyErr_BadInternalCall ();
12701411 return NULL ;
12711412 }
1272- break ;
1413+ char * buf = (char * )PyMem_Malloc (_Py_DOUBLE_REPR_BUFSIZE );
1414+ if (buf == NULL ) {
1415+ PyErr_NoMemory ();
1416+ return NULL ;
1417+ }
1418+ double_repr_buffered (val , buf , _Py_DOUBLE_REPR_BUFSIZE , flags , type );
1419+ return buf ;
1420+ }
12731421
12741422 default :
12751423 PyErr_BadInternalCall ();
0 commit comments