@@ -179,39 +179,40 @@ typedef enum {
179
179
} parse_dec_in_t ;
180
180
181
181
#if MICROPY_PY_BUILTINS_FLOAT
182
- // DEC_VAL_MAX only needs to be rough and is used to retain precision while not overflowing
182
+ // MANTISSA_MAX is used to retain precision while not overflowing mantissa
183
183
// SMALL_NORMAL_VAL is the smallest power of 10 that is still a normal float
184
184
// EXACT_POWER_OF_10 is the largest value of x so that 10^x can be stored exactly in a float
185
185
// Note: EXACT_POWER_OF_10 is at least floor(log_5(2^mantissa_length)). Indeed, 10^n = 2^n * 5^n
186
186
// so we only have to store the 5^n part in the mantissa (the 2^n part will go into the float's
187
187
// exponent).
188
188
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
189
- #define DEC_VAL_MAX 1e20F
189
+ #define MANTISSA_MAX 0x19999998U
190
190
#define SMALL_NORMAL_VAL (1e-37F)
191
191
#define SMALL_NORMAL_EXP (-37)
192
192
#define EXACT_POWER_OF_10 (9)
193
193
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
194
- #define DEC_VAL_MAX 1e200
194
+ #define MANTISSA_MAX 0x1999999999999998ULL
195
195
#define SMALL_NORMAL_VAL (1e-307)
196
196
#define SMALL_NORMAL_EXP (-307)
197
197
#define EXACT_POWER_OF_10 (22)
198
198
#endif
199
199
200
200
// Break out inner digit accumulation routine to ease trailing zero deferral.
201
- static void accept_digit (mp_float_t * p_dec_val , int dig , int * p_exp_extra , int in ) {
201
+ static mp_float_uint_t accept_digit (mp_float_uint_t p_mantissa , unsigned int dig , int * p_exp_extra , int in ) {
202
202
// Core routine to ingest an additional digit.
203
- if (* p_dec_val < DEC_VAL_MAX ) {
203
+ if (p_mantissa < MANTISSA_MAX ) {
204
204
// dec_val won't overflow so keep accumulating
205
- * p_dec_val = 10 * * p_dec_val + dig ;
206
205
if (in == PARSE_DEC_IN_FRAC ) {
207
206
-- (* p_exp_extra );
208
207
}
208
+ return 10u * p_mantissa + dig ;
209
209
} else {
210
210
// dec_val might overflow and we anyway can't represent more digits
211
211
// of precision, so ignore the digit and just adjust the exponent
212
212
if (in == PARSE_DEC_IN_INTG ) {
213
213
++ (* p_exp_extra );
214
214
}
215
+ return p_mantissa ;
215
216
}
216
217
}
217
218
#endif // MICROPY_PY_BUILTINS_FLOAT
@@ -273,6 +274,7 @@ mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lex
273
274
// string should be a decimal number
274
275
parse_dec_in_t in = PARSE_DEC_IN_INTG ;
275
276
bool exp_neg = false;
277
+ mp_float_uint_t mantissa = 0 ;
276
278
int exp_val = 0 ;
277
279
int exp_extra = 0 ;
278
280
int trailing_zeros_intg = 0 , trailing_zeros_frac = 0 ;
@@ -288,9 +290,9 @@ mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lex
288
290
exp_val = 10 * exp_val + dig ;
289
291
}
290
292
} else {
291
- if (dig == 0 || dec_val >= DEC_VAL_MAX ) {
293
+ if (dig == 0 || mantissa >= MANTISSA_MAX ) {
292
294
// Defer treatment of zeros in fractional part. If nothing comes afterwards, ignore them.
293
- // Also, once we reach DEC_VAL_MAX , treat every additional digit as a trailing zero.
295
+ // Also, once we reach MANTISSA_MAX , treat every additional digit as a trailing zero.
294
296
if (in == PARSE_DEC_IN_INTG ) {
295
297
++ trailing_zeros_intg ;
296
298
} else {
@@ -299,14 +301,14 @@ mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lex
299
301
} else {
300
302
// Time to un-defer any trailing zeros. Intg zeros first.
301
303
while (trailing_zeros_intg ) {
302
- accept_digit (& dec_val , 0 , & exp_extra , PARSE_DEC_IN_INTG );
304
+ mantissa = accept_digit (mantissa , 0 , & exp_extra , PARSE_DEC_IN_INTG );
303
305
-- trailing_zeros_intg ;
304
306
}
305
307
while (trailing_zeros_frac ) {
306
- accept_digit (& dec_val , 0 , & exp_extra , PARSE_DEC_IN_FRAC );
308
+ mantissa = accept_digit (mantissa , 0 , & exp_extra , PARSE_DEC_IN_FRAC );
307
309
-- trailing_zeros_frac ;
308
310
}
309
- accept_digit (& dec_val , dig , & exp_extra , in );
311
+ mantissa = accept_digit (mantissa , dig , & exp_extra , in );
310
312
}
311
313
}
312
314
} else if (in == PARSE_DEC_IN_INTG && dig == '.' ) {
@@ -340,6 +342,7 @@ mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lex
340
342
341
343
// apply the exponent, making sure it's not a subnormal value
342
344
exp_val += exp_extra + trailing_zeros_intg ;
345
+ dec_val = (mp_float_t )mantissa ;
343
346
if (exp_val < SMALL_NORMAL_EXP ) {
344
347
exp_val -= SMALL_NORMAL_EXP ;
345
348
dec_val *= SMALL_NORMAL_VAL ;
0 commit comments