@@ -96,8 +96,22 @@ static inline int fp_isless1(float x) {
96
96
#define fp_iszero (x ) (x == 0)
97
97
#define fp_isless1 (x ) (x < 1.0)
98
98
99
+ union floatbits {
100
+ double f ;
101
+ uint64_t u ;
102
+ };
103
+
99
104
#endif // MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT/DOUBLE
100
105
106
+ static inline int fp_ge_eps (FPTYPE x , FPTYPE y ) {
107
+ union floatbits fb_y = {y };
108
+ // Back off 2 eps.
109
+ // This is valid for almost all values, but in practice
110
+ // it's only used when y = 1eX for X>=0.
111
+ fb_y .u -= 2 ;
112
+ return (x >= fb_y .f );
113
+ }
114
+
101
115
static const FPTYPE g_pos_pow [] = {
102
116
#if FPDECEXP > 32
103
117
MICROPY_FLOAT_CONST (1e256 ), MICROPY_FLOAT_CONST (1e128 ), MICROPY_FLOAT_CONST (1e64 ),
@@ -254,14 +268,14 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
254
268
// mantissa.
255
269
FPTYPE u_base = FPCONST (1.0 );
256
270
for (e = 0 , e1 = FPDECEXP ; e1 ; e1 >>= 1 , pos_pow ++ ) {
257
- // Use "volatile" to force the result to be stored in a float64.
258
- // Without this, nanbox build would sometimes fail to report
259
- // "equality" leading to weird results.
260
- #if defined(__i386__ )
261
- volatile
262
- #endif
263
271
FPTYPE next_u = u_base * * pos_pow ;
264
- if (f >= next_u ) {
272
+ // fp_ge_eps performs "f >= (next_u - 2eps)" so that if, for
273
+ // numerical reasons, f is very close to a power of ten but
274
+ // not strictly equal, we still treat it as that power of 10.
275
+ // The comparison was failing for maybe 10% of 1eX values, but
276
+ // although rounding fixed many of them, there were still some
277
+ // rendering as 9.99999998e(X-1).
278
+ if (fp_ge_eps (f , next_u )) {
265
279
u_base = next_u ;
266
280
e += e1 ;
267
281
}
@@ -359,9 +373,11 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
359
373
}
360
374
}
361
375
}
362
- // Figure how many u_bases we can fit into f.
363
376
for (d = 0 ; d < 9 ; ++ d ) {
364
- if (f < u_base ) {
377
+ // This is essentially "if (f < u_base)", but with 2eps margin
378
+ // so that if f is just a tiny bit smaller, we treat it as
379
+ // equal (and accept the additional digit value).
380
+ if (!fp_ge_eps (f , u_base )) {
365
381
break ;
366
382
}
367
383
f -= u_base ;
0 commit comments