@@ -197,6 +197,23 @@ typedef enum {
197
197
#define EXACT_POWER_OF_10 (22)
198
198
#endif
199
199
200
+ mp_float_t mp_decimal_exp (mp_float_t num , int exp_val ) {
201
+ if (exp_val == 0 ) {
202
+ return num ;
203
+ }
204
+ // If possible, we would rather manipulate numbers that have an exact representation
205
+ // in IEEE754. It turns out small positive powers of 10 do, whereas small negative
206
+ // powers of 10 don't. So in that case, we'll yield a division of exact values rather
207
+ // than a multiplication of slightly erroneous values.
208
+ if (exp_val < 0 && exp_val >= - EXACT_POWER_OF_10 ) {
209
+ num /= MICROPY_FLOAT_C_FUN (pow )(10 , - exp_val );
210
+ } else {
211
+ num *= MICROPY_FLOAT_C_FUN (pow )(10 , exp_val );
212
+ }
213
+ return num ;
214
+ }
215
+
216
+
200
217
// Break out inner digit accumulation routine to ease trailing zero deferral.
201
218
static mp_float_uint_t accept_digit (mp_float_uint_t p_mantissa , unsigned int dig , int * p_exp_extra , int in ) {
202
219
// Core routine to ingest an additional digit.
@@ -215,6 +232,92 @@ static mp_float_uint_t accept_digit(mp_float_uint_t p_mantissa, unsigned int dig
215
232
return p_mantissa ;
216
233
}
217
234
}
235
+
236
+ // internal function to parse an unsigned decimal number
237
+ const char * mp_parse_float_internal (const char * str , size_t len , mp_float_t * res ) {
238
+ const char * top = str + len ;
239
+
240
+ parse_dec_in_t in = PARSE_DEC_IN_INTG ;
241
+ bool exp_neg = false;
242
+ mp_float_uint_t mantissa = 0 ;
243
+ int exp_val = 0 ;
244
+ int exp_extra = 0 ;
245
+ int trailing_zeros_intg = 0 , trailing_zeros_frac = 0 ;
246
+ while (str < top ) {
247
+ unsigned int dig = * str ++ ;
248
+ if ('0' <= dig && dig <= '9' ) {
249
+ dig -= '0' ;
250
+ if (in == PARSE_DEC_IN_EXP ) {
251
+ // don't overflow exp_val when adding next digit, instead just truncate
252
+ // it and the resulting float will still be correct, either inf or 0.0
253
+ // (use INT_MAX/2 to allow adding exp_extra at the end without overflow)
254
+ if (exp_val < (INT_MAX / 2 - 9 ) / 10 ) {
255
+ exp_val = 10 * exp_val + dig ;
256
+ }
257
+ } else {
258
+ if (dig == 0 || mantissa >= MANTISSA_MAX ) {
259
+ // Defer treatment of zeros in fractional part. If nothing comes afterwards, ignore them.
260
+ // Also, once we reach MANTISSA_MAX, treat every additional digit as a trailing zero.
261
+ if (in == PARSE_DEC_IN_INTG ) {
262
+ ++ trailing_zeros_intg ;
263
+ } else {
264
+ ++ trailing_zeros_frac ;
265
+ }
266
+ } else {
267
+ // Time to un-defer any trailing zeros. Intg zeros first.
268
+ while (trailing_zeros_intg ) {
269
+ mantissa = accept_digit (mantissa , 0 , & exp_extra , PARSE_DEC_IN_INTG );
270
+ -- trailing_zeros_intg ;
271
+ }
272
+ while (trailing_zeros_frac ) {
273
+ mantissa = accept_digit (mantissa , 0 , & exp_extra , PARSE_DEC_IN_FRAC );
274
+ -- trailing_zeros_frac ;
275
+ }
276
+ mantissa = accept_digit (mantissa , dig , & exp_extra , in );
277
+ }
278
+ }
279
+ } else if (in == PARSE_DEC_IN_INTG && dig == '.' ) {
280
+ in = PARSE_DEC_IN_FRAC ;
281
+ } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20 ) == 'e' )) {
282
+ in = PARSE_DEC_IN_EXP ;
283
+ if (str < top ) {
284
+ if (str [0 ] == '+' ) {
285
+ str ++ ;
286
+ } else if (str [0 ] == '-' ) {
287
+ str ++ ;
288
+ exp_neg = true;
289
+ }
290
+ }
291
+ if (str == top ) {
292
+ return NULL ;
293
+ }
294
+ } else if (dig == '_' ) {
295
+ continue ;
296
+ } else {
297
+ // unknown character
298
+ str -- ;
299
+ break ;
300
+ }
301
+ }
302
+
303
+ // work out the exponent
304
+ if (exp_neg ) {
305
+ exp_val = - exp_val ;
306
+ }
307
+
308
+ // apply the exponent, making sure it's not a subnormal value
309
+ exp_val += exp_extra + trailing_zeros_intg ;
310
+ mp_float_t dec_val = (mp_float_t )mantissa ;
311
+ if (exp_val < SMALL_NORMAL_EXP ) {
312
+ exp_val -= SMALL_NORMAL_EXP ;
313
+ dec_val *= SMALL_NORMAL_VAL ;
314
+ }
315
+
316
+ // At this point, we just need to multiply the mantissa by its base 10 exponent.
317
+ * res = mp_decimal_exp (dec_val , exp_val );
318
+
319
+ return str ;
320
+ }
218
321
#endif // MICROPY_PY_BUILTINS_FLOAT
219
322
220
323
#if MICROPY_PY_BUILTINS_COMPLEX
@@ -272,91 +375,9 @@ mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lex
272
375
}
273
376
} else {
274
377
// string should be a decimal number
275
- parse_dec_in_t in = PARSE_DEC_IN_INTG ;
276
- bool exp_neg = false;
277
- mp_float_uint_t mantissa = 0 ;
278
- int exp_val = 0 ;
279
- int exp_extra = 0 ;
280
- int trailing_zeros_intg = 0 , trailing_zeros_frac = 0 ;
281
- while (str < top ) {
282
- unsigned int dig = * str ++ ;
283
- if ('0' <= dig && dig <= '9' ) {
284
- dig -= '0' ;
285
- if (in == PARSE_DEC_IN_EXP ) {
286
- // don't overflow exp_val when adding next digit, instead just truncate
287
- // it and the resulting float will still be correct, either inf or 0.0
288
- // (use INT_MAX/2 to allow adding exp_extra at the end without overflow)
289
- if (exp_val < (INT_MAX / 2 - 9 ) / 10 ) {
290
- exp_val = 10 * exp_val + dig ;
291
- }
292
- } else {
293
- if (dig == 0 || mantissa >= MANTISSA_MAX ) {
294
- // Defer treatment of zeros in fractional part. If nothing comes afterwards, ignore them.
295
- // Also, once we reach MANTISSA_MAX, treat every additional digit as a trailing zero.
296
- if (in == PARSE_DEC_IN_INTG ) {
297
- ++ trailing_zeros_intg ;
298
- } else {
299
- ++ trailing_zeros_frac ;
300
- }
301
- } else {
302
- // Time to un-defer any trailing zeros. Intg zeros first.
303
- while (trailing_zeros_intg ) {
304
- mantissa = accept_digit (mantissa , 0 , & exp_extra , PARSE_DEC_IN_INTG );
305
- -- trailing_zeros_intg ;
306
- }
307
- while (trailing_zeros_frac ) {
308
- mantissa = accept_digit (mantissa , 0 , & exp_extra , PARSE_DEC_IN_FRAC );
309
- -- trailing_zeros_frac ;
310
- }
311
- mantissa = accept_digit (mantissa , dig , & exp_extra , in );
312
- }
313
- }
314
- } else if (in == PARSE_DEC_IN_INTG && dig == '.' ) {
315
- in = PARSE_DEC_IN_FRAC ;
316
- } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20 ) == 'e' )) {
317
- in = PARSE_DEC_IN_EXP ;
318
- if (str < top ) {
319
- if (str [0 ] == '+' ) {
320
- str ++ ;
321
- } else if (str [0 ] == '-' ) {
322
- str ++ ;
323
- exp_neg = true;
324
- }
325
- }
326
- if (str == top ) {
327
- goto value_error ;
328
- }
329
- } else if (dig == '_' ) {
330
- continue ;
331
- } else {
332
- // unknown character
333
- str -- ;
334
- break ;
335
- }
336
- }
337
-
338
- // work out the exponent
339
- if (exp_neg ) {
340
- exp_val = - exp_val ;
341
- }
342
-
343
- // apply the exponent, making sure it's not a subnormal value
344
- exp_val += exp_extra + trailing_zeros_intg ;
345
- dec_val = (mp_float_t )mantissa ;
346
- if (exp_val < SMALL_NORMAL_EXP ) {
347
- exp_val -= SMALL_NORMAL_EXP ;
348
- dec_val *= SMALL_NORMAL_VAL ;
349
- }
350
-
351
- // At this point, we need to multiply the mantissa by its base 10 exponent. If possible,
352
- // we would rather manipulate numbers that have an exact representation in IEEE754. It
353
- // turns out small positive powers of 10 do, whereas small negative powers of 10 don't.
354
- // So in that case, we'll yield a division of exact values rather than a multiplication
355
- // of slightly erroneous values.
356
- if (exp_val < 0 && exp_val >= - EXACT_POWER_OF_10 ) {
357
- dec_val /= MICROPY_FLOAT_C_FUN (pow )(10 , - exp_val );
358
- } else {
359
- dec_val *= MICROPY_FLOAT_C_FUN (pow )(10 , exp_val );
378
+ str = mp_parse_float_internal (str , top - str , & dec_val );
379
+ if (!str ) {
380
+ goto value_error ;
360
381
}
361
382
}
362
383
0 commit comments