Parse a decimal floating-point number into IEEE 754 single-precision bits.
Accepts the usual decimal syntax: optional sign, integer digits, optional fractional part, optional e/E exponent. Returns the IEEE 754 single-precision bit pattern of the parsed value. Caller bit-casts to float via fl::bit_cast<float>(bits) if needed.
No FP arithmetic is performed. The implementation uses only integer shifts, masks, and 32x32->64 widening multiplies – libgcc soft-FP helpers (__aeabi_d*, __aeabi_f*) are never reached.
261 {
262 fl::size i = 0;
263
264 auto fail = [&]() -> u32 {
265 if (consumed) *consumed = 0;
266 return 0;
267 };
268
269
270 while (i < len && (s[i] == ' ' || s[i] == '\t' || s[i] == '\n' ||
271 s[i] == '\r' || s[i] == '\f' || s[i] == '\v')) {
272 ++i;
273 }
274
275
276 u32 sign_bit = 0;
277 if (i < len && s[i] ==
'-') { sign_bit =
kSignBitMask; ++i; }
278 else if (i < len && s[i] == '+') { ++i; }
279
280
281
282
283
285 int decimal_exp = 0;
286 int significant_digits = 0;
287 bool seen_decimal = false;
288 bool seen_digit = false;
289 constexpr int kMaxSignificantDigits = 19;
290
291 while (i < len) {
292 const char c = s[i];
293 if (c >= '0' && c <= '9') {
294 seen_digit = true;
295 if (significant_digits < kMaxSignificantDigits) {
296
297 mantissa = mantissa * 10u +
static_cast<fl::u64>(c -
'0');
298 if (significant_digits != 0 || c != '0') {
299 ++significant_digits;
300 }
301 if (seen_decimal) {
302 --decimal_exp;
303 }
304 } else {
305
306 if (!seen_decimal) {
307 ++decimal_exp;
308 }
309 }
310 ++i;
311 } else if (c == '.' && !seen_decimal) {
312 seen_decimal = true;
313 ++i;
314 } else {
315 break;
316 }
317 }
318
319
320
321
322 if (!seen_digit) {
324 }
325
326
327 if (i < len && (s[i] == 'e' || s[i] == 'E')) {
328 const fl::size exp_start = i + 1;
329 fl::size j = exp_start;
330 int exp_sign = 1;
331 if (j < len && s[j] == '-') { exp_sign = -1; ++j; }
332 else if (j < len && s[j] == '+') { ++j; }
333 int exp_val = 0;
334 const fl::size digits_begin = j;
335 while (j < len && s[j] >= '0' && s[j] <= '9') {
336 if (exp_val < 10000) {
337 exp_val = exp_val * 10 + (s[j] - '0');
338 }
339 ++j;
340 }
341 if (j != digits_begin) {
342 decimal_exp += exp_sign * exp_val;
343 i = j;
344 }
345
346 }
347
348 if (consumed) *consumed = i;
349
350 if (mantissa == 0) {
351 return sign_bit;
352 }
353
354
355
356 int mantissa_shift = 0;
357 while ((mantissa & 0x8000000000000000ull) == 0) {
358 mantissa <<= 1;
359 ++mantissa_shift;
360 }
361
362
363
364
365
366
367 if (decimal_exp < kPow10KMin) {
368 return sign_bit;
369 }
370 if (decimal_exp > kPow10KMax) {
372 }
373
374 const fl::size idx =
static_cast<fl::size
>(decimal_exp -
kPow10KMin);
377
379
380
381
382 int extra_shift = 0;
383 if ((product_hi & 0x8000000000000000ull) == 0) {
384 product_hi <<= 1;
385 extra_shift = 1;
386 }
387
388
389
390
391 int bin_exp = -mantissa_shift + pow_exp + 64 - extra_shift;
392
393
394
395 int biased_exp = bin_exp + 63 + 127;
396
397 if (biased_exp >= 0xFF) {
399 }
400 if (biased_exp <= 0) {
401
402
403
404 return sign_bit;
405 }
406
407
408
409
410
411 fl::u32 ieee_mant = static_cast<fl::u32>((product_hi >> 40) & 0x7FFFFFu);
412 const fl::u64 round_bit = (product_hi >> 39) & 1u;
413 const fl::u64 sticky = (product_hi & 0x7FFFFFFFFFull);
414 if (round_bit && (sticky != 0 || (ieee_mant & 1u))) {
415 ++ieee_mant;
416 if (ieee_mant == (1u << 23)) {
417
418 ieee_mant = 0;
419 ++biased_exp;
420 if (biased_exp >= 0xFF) {
422 }
423 }
424 }
425
426 return sign_bit | (static_cast<fl::u32>(biased_exp) << 23) | ieee_mant;
427}
static constexpr fl::u64 kPow10Mant[kPow10Count]
constexpr fl::u32 kInfBitsPos
static constexpr fl::i16 kPow10BExp[kPow10Count]
constexpr fl::u32 kSignBitMask
fl::u64 mul_hi_u64(fl::u64 a, fl::u64 b) FL_NOEXCEPT
static constexpr int kPow10KMin
void fail(const char *msg, const char *file, int line, bool isFatal) FL_NOEXCEPT
Helper for FAIL macros.