Skip to content

Commit 7417ccf

Browse files
committed
py/formatfloat: Add ability to format doubles with exponents > 99.
For single prec, exponents never get larger than about 37. For double prec, exponents can be larger than 99 and need 3 bytes to format. This patch makes the number of bytes needed configurable. Addresses issue #1772.
1 parent d3b1f0b commit 7417ccf

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

py/formatfloat.c

+18-10
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#define FPCONST(x) x##F
5757
#define FPROUND_TO_ONE 0.9999995F
5858
#define FPDECEXP 32
59+
#define FPMIN_BUF_SIZE 6 // +9e+99
5960

6061
#define FLT_SIGN_MASK 0x80000000
6162
#define FLT_EXP_MASK 0x7F800000
@@ -79,6 +80,7 @@ static inline int fp_isless1(float x) { union floatbits fb = {x}; return fb.u <
7980
#define FPCONST(x) x
8081
#define FPROUND_TO_ONE 0.999999999995
8182
#define FPDECEXP 256
83+
#define FPMIN_BUF_SIZE 7 // +9e+199
8284
#include <math.h>
8385
#define fp_signbit(x) signbit(x)
8486
#define fp_isspecial(x) 1
@@ -105,11 +107,11 @@ static const FPTYPE g_neg_pow[] = {
105107
int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) {
106108

107109
char *s = buf;
108-
int buf_remaining = buf_size - 1;
109110

110-
if (buf_size < 7) {
111-
// Smallest exp notion is -9e+99 which is 6 chars plus terminating
112-
// null.
111+
if (buf_size <= FPMIN_BUF_SIZE) {
112+
// FPMIN_BUF_SIZE is the minimum size needed to store any FP number.
113+
// If the buffer does not have enough room for this (plus null terminator)
114+
// then don't try to format the float.
113115

114116
if (buf_size >= 2) {
115117
*s++ = '?';
@@ -127,7 +129,10 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
127129
*s++ = sign;
128130
}
129131
}
130-
buf_remaining -= (s - buf); // Adjust for sign
132+
133+
// buf_remaining contains bytes available for digits and exponent.
134+
// It is buf_size minus room for the sign and null byte.
135+
int buf_remaining = buf_size - 1 - (s - buf);
131136

132137
if (fp_isspecial(f)) {
133138
char uc = fmt & 0x20;
@@ -226,8 +231,8 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
226231
e_sign = e_sign_char;
227232
dec = 0;
228233

229-
if (prec > (buf_remaining - 6)) {
230-
prec = buf_remaining - 6;
234+
if (prec > (buf_remaining - FPMIN_BUF_SIZE)) {
235+
prec = buf_remaining - FPMIN_BUF_SIZE;
231236
if (fmt == 'g') {
232237
prec++;
233238
}
@@ -258,8 +263,8 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
258263
}
259264
}
260265
}
261-
if (fmt == 'e' && prec > (buf_remaining - 6)) {
262-
prec = buf_remaining - 6;
266+
if (fmt == 'e' && prec > (buf_remaining - FPMIN_BUF_SIZE)) {
267+
prec = buf_remaining - FPMIN_BUF_SIZE;
263268
}
264269
// If the user specified 'g' format, and e is < prec, then we'll switch
265270
// to the fixed format.
@@ -377,7 +382,10 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
377382
if (e_sign) {
378383
*s++ = e_char;
379384
*s++ = e_sign;
380-
*s++ = '0' + (e / 10);
385+
if (FPMIN_BUF_SIZE == 7 && e >= 100) {
386+
*s++ = '0' + (e / 100);
387+
}
388+
*s++ = '0' + ((e / 10) % 10);
381389
*s++ = '0' + (e % 10);
382390
}
383391
*s = '\0';

0 commit comments

Comments
 (0)