@@ -195,6 +195,8 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m
195
195
}
196
196
}
197
197
198
+ #if MICROPY_PY_BUILTINS_FLOAT
199
+
198
200
enum {
199
201
REAL_IMAG_STATE_START = 0 ,
200
202
REAL_IMAG_STATE_HAVE_REAL = 1 ,
@@ -207,25 +209,39 @@ typedef enum {
207
209
PARSE_DEC_IN_EXP ,
208
210
} parse_dec_in_t ;
209
211
210
- #if MICROPY_PY_BUILTINS_FLOAT
211
212
// MANTISSA_MAX is used to retain precision while not overflowing mantissa
212
- // SMALL_NORMAL_VAL is the smallest power of 10 that is still a normal float
213
- // EXACT_POWER_OF_10 is the largest value of x so that 10^x can be stored exactly in a float
214
- // Note: EXACT_POWER_OF_10 is at least floor(log_5(2^mantissa_length)). Indeed, 10^n = 2^n * 5^n
215
- // so we only have to store the 5^n part in the mantissa (the 2^n part will go into the float's
216
- // exponent).
213
+ #define MANTISSA_MAX (sizeof(mp_float_uint_t) == 8 ? 0x1999999999999998ULL : 0x19999998U)
214
+
215
+ // MAX_EXACT_POWER_OF_5 is the largest value of x so that 5^x can be stored exactly in a float
217
216
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
218
- #define MANTISSA_MAX 0x19999998U
219
- #define SMALL_NORMAL_VAL (1e-37F)
220
- #define SMALL_NORMAL_EXP (-37)
221
- #define EXACT_POWER_OF_10 (9)
217
+ #define MAX_EXACT_POWER_OF_5 (10)
222
218
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
223
- #define MANTISSA_MAX 0x1999999999999998ULL
224
- #define SMALL_NORMAL_VAL (1e-307)
225
- #define SMALL_NORMAL_EXP (-307)
226
- #define EXACT_POWER_OF_10 (22)
219
+ #define MAX_EXACT_POWER_OF_5 (22)
227
220
#endif
228
221
222
+ // Helper to compute `num * (10.0 ** dec_exp)`
223
+ mp_float_t mp_decimal_exp (mp_float_t num , int dec_exp ) {
224
+
225
+ if (dec_exp == 0 || num == MICROPY_FLOAT_CONST (0.0 )) {
226
+ return num ;
227
+ }
228
+ mp_float_union_t res = {num };
229
+ // Multiply first by (2.0 ** dec_exp) via the exponent
230
+ // - this will ensure that the result of `pow()` is always in mp_float_t range
231
+ // when the result is expected to be in mp_float_t range (e.g. during format)
232
+ // - we don't need to care about p.exp overflow, as (5.0 ** dec_exp) will anyway
233
+ // force the final result toward the proper edge if needed (0.0 or inf)
234
+ res .p .exp += dec_exp ;
235
+ // Use positive exponents when they are more precise then negative
236
+ if (dec_exp < 0 && dec_exp >= - MAX_EXACT_POWER_OF_5 ) {
237
+ res .f /= MICROPY_FLOAT_C_FUN (pow )(5 , - dec_exp );
238
+ } else {
239
+ res .f *= MICROPY_FLOAT_C_FUN (pow )(5 , dec_exp );
240
+ }
241
+ return (mp_float_t )res .f ;
242
+ }
243
+
244
+
229
245
// Break out inner digit accumulation routine to ease trailing zero deferral.
230
246
static mp_float_uint_t accept_digit (mp_float_uint_t p_mantissa , unsigned int dig , int * p_exp_extra , int in ) {
231
247
// Core routine to ingest an additional digit.
@@ -244,6 +260,85 @@ static mp_float_uint_t accept_digit(mp_float_uint_t p_mantissa, unsigned int dig
244
260
return p_mantissa ;
245
261
}
246
262
}
263
+
264
+ // Helper to parse an unsigned decimal number into a mp_float_t
265
+ const char * mp_parse_float_internal (const char * str , size_t len , mp_float_t * res ) {
266
+ const char * top = str + len ;
267
+
268
+ parse_dec_in_t in = PARSE_DEC_IN_INTG ;
269
+ bool exp_neg = false;
270
+ mp_float_uint_t mantissa = 0 ;
271
+ int exp_val = 0 ;
272
+ int exp_extra = 0 ;
273
+ int trailing_zeros_intg = 0 , trailing_zeros_frac = 0 ;
274
+ while (str < top ) {
275
+ unsigned int dig = * str ++ ;
276
+ if ('0' <= dig && dig <= '9' ) {
277
+ dig -= '0' ;
278
+ if (in == PARSE_DEC_IN_EXP ) {
279
+ // don't overflow exp_val when adding next digit, instead just truncate
280
+ // it and the resulting float will still be correct, either inf or 0.0
281
+ // (use INT_MAX/2 to allow adding exp_extra at the end without overflow)
282
+ if (exp_val < (INT_MAX / 2 - 9 ) / 10 ) {
283
+ exp_val = 10 * exp_val + dig ;
284
+ }
285
+ } else {
286
+ if (dig == 0 || mantissa >= MANTISSA_MAX ) {
287
+ // Defer treatment of zeros in fractional part. If nothing comes afterwards, ignore them.
288
+ // Also, once we reach MANTISSA_MAX, treat every additional digit as a trailing zero.
289
+ if (in == PARSE_DEC_IN_INTG ) {
290
+ ++ trailing_zeros_intg ;
291
+ } else {
292
+ ++ trailing_zeros_frac ;
293
+ }
294
+ } else {
295
+ // Time to un-defer any trailing zeros. Intg zeros first.
296
+ while (trailing_zeros_intg ) {
297
+ mantissa = accept_digit (mantissa , 0 , & exp_extra , PARSE_DEC_IN_INTG );
298
+ -- trailing_zeros_intg ;
299
+ }
300
+ while (trailing_zeros_frac ) {
301
+ mantissa = accept_digit (mantissa , 0 , & exp_extra , PARSE_DEC_IN_FRAC );
302
+ -- trailing_zeros_frac ;
303
+ }
304
+ mantissa = accept_digit (mantissa , dig , & exp_extra , in );
305
+ }
306
+ }
307
+ } else if (in == PARSE_DEC_IN_INTG && dig == '.' ) {
308
+ in = PARSE_DEC_IN_FRAC ;
309
+ } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20 ) == 'e' )) {
310
+ in = PARSE_DEC_IN_EXP ;
311
+ if (str < top ) {
312
+ if (str [0 ] == '+' ) {
313
+ str ++ ;
314
+ } else if (str [0 ] == '-' ) {
315
+ str ++ ;
316
+ exp_neg = true;
317
+ }
318
+ }
319
+ if (str == top ) {
320
+ return NULL ;
321
+ }
322
+ } else if (dig == '_' ) {
323
+ continue ;
324
+ } else {
325
+ // unknown character
326
+ str -- ;
327
+ break ;
328
+ }
329
+ }
330
+
331
+ // work out the exponent
332
+ if (exp_neg ) {
333
+ exp_val = - exp_val ;
334
+ }
335
+ exp_val += exp_extra + trailing_zeros_intg ;
336
+
337
+ // At this point, we just need to multiply the mantissa by its base 10 exponent.
338
+ * res = (mp_float_t )mp_decimal_exp (mantissa , exp_val );
339
+
340
+ return str ;
341
+ }
247
342
#endif // MICROPY_PY_BUILTINS_FLOAT
248
343
249
344
#if MICROPY_PY_BUILTINS_COMPLEX
@@ -295,91 +390,9 @@ parse_start:;
295
390
dec_val = MICROPY_FLOAT_C_FUN (nan )("" );
296
391
} else {
297
392
// string should be a decimal number
298
- parse_dec_in_t in = PARSE_DEC_IN_INTG ;
299
- bool exp_neg = false;
300
- mp_float_uint_t mantissa = 0 ;
301
- int exp_val = 0 ;
302
- int exp_extra = 0 ;
303
- int trailing_zeros_intg = 0 , trailing_zeros_frac = 0 ;
304
- while (str < top ) {
305
- unsigned int dig = * str ++ ;
306
- if ('0' <= dig && dig <= '9' ) {
307
- dig -= '0' ;
308
- if (in == PARSE_DEC_IN_EXP ) {
309
- // don't overflow exp_val when adding next digit, instead just truncate
310
- // it and the resulting float will still be correct, either inf or 0.0
311
- // (use INT_MAX/2 to allow adding exp_extra at the end without overflow)
312
- if (exp_val < (INT_MAX / 2 - 9 ) / 10 ) {
313
- exp_val = 10 * exp_val + dig ;
314
- }
315
- } else {
316
- if (dig == 0 || mantissa >= MANTISSA_MAX ) {
317
- // Defer treatment of zeros in fractional part. If nothing comes afterwards, ignore them.
318
- // Also, once we reach MANTISSA_MAX, treat every additional digit as a trailing zero.
319
- if (in == PARSE_DEC_IN_INTG ) {
320
- ++ trailing_zeros_intg ;
321
- } else {
322
- ++ trailing_zeros_frac ;
323
- }
324
- } else {
325
- // Time to un-defer any trailing zeros. Intg zeros first.
326
- while (trailing_zeros_intg ) {
327
- mantissa = accept_digit (mantissa , 0 , & exp_extra , PARSE_DEC_IN_INTG );
328
- -- trailing_zeros_intg ;
329
- }
330
- while (trailing_zeros_frac ) {
331
- mantissa = accept_digit (mantissa , 0 , & exp_extra , PARSE_DEC_IN_FRAC );
332
- -- trailing_zeros_frac ;
333
- }
334
- mantissa = accept_digit (mantissa , dig , & exp_extra , in );
335
- }
336
- }
337
- } else if (in == PARSE_DEC_IN_INTG && dig == '.' ) {
338
- in = PARSE_DEC_IN_FRAC ;
339
- } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20 ) == 'e' )) {
340
- in = PARSE_DEC_IN_EXP ;
341
- if (str < top ) {
342
- if (str [0 ] == '+' ) {
343
- str ++ ;
344
- } else if (str [0 ] == '-' ) {
345
- str ++ ;
346
- exp_neg = true;
347
- }
348
- }
349
- if (str == top ) {
350
- goto value_error ;
351
- }
352
- } else if (dig == '_' ) {
353
- continue ;
354
- } else {
355
- // unknown character
356
- str -- ;
357
- break ;
358
- }
359
- }
360
-
361
- // work out the exponent
362
- if (exp_neg ) {
363
- exp_val = - exp_val ;
364
- }
365
-
366
- // apply the exponent, making sure it's not a subnormal value
367
- exp_val += exp_extra + trailing_zeros_intg ;
368
- dec_val = (mp_float_t )mantissa ;
369
- if (exp_val < SMALL_NORMAL_EXP ) {
370
- exp_val -= SMALL_NORMAL_EXP ;
371
- dec_val *= SMALL_NORMAL_VAL ;
372
- }
373
-
374
- // At this point, we need to multiply the mantissa by its base 10 exponent. If possible,
375
- // we would rather manipulate numbers that have an exact representation in IEEE754. It
376
- // turns out small positive powers of 10 do, whereas small negative powers of 10 don't.
377
- // So in that case, we'll yield a division of exact values rather than a multiplication
378
- // of slightly erroneous values.
379
- if (exp_val < 0 && exp_val >= - EXACT_POWER_OF_10 ) {
380
- dec_val /= MICROPY_FLOAT_C_FUN (pow )(10 , - exp_val );
381
- } else {
382
- dec_val *= MICROPY_FLOAT_C_FUN (pow )(10 , exp_val );
393
+ str = mp_parse_float_internal (str , top - str , & dec_val );
394
+ if (!str ) {
395
+ goto value_error ;
383
396
}
384
397
}
385
398
0 commit comments