Commit Graph

16 Commits

Author SHA1 Message Date
Stephen Canon 2972c44201 Fix bug in String->Double conversion (#88682)
The existing code (new in 6.4) has a special case for when the exponent
was zero to do a straight conversion instead of splitting the integer
and doing an FMA. However, this either gave incorrect results or trapped
when signed `digits` was too large to fit into an `Int64`. The old
approach could be made to work without too much fuss, but we can also
just let this case fall through and use the non-zero exponent path,
which simplifies the code somewhat. We might want to rework all of this
in the future for further performance gains, but this simplifying fix is
totally straightforward and easy to take for now.

Resolves rdar://175568950

<!-- Please fill out the following form: --> 
- **Explanation**:
Eliminates a special case for String->Double conversion that introduced
a bug for certain values, allowing execution to fall through into more
general code that handles the special case correctly as well.
- **Scope**:
Narrowly-focused. Allows us to get the correct result for some inputs
that would otherwise regress in 6.4 and produce values of the wrong
sign.
- **Issues**:
rdar://175568950
- **Risk**:
Low
- **Testing**:
No special testing required; added new test cases to the stdlib tests to
exercise the paths in question.
2026-04-27 16:47:04 -07:00
Guillaume Lessard db0ca0fc23 [stdlib] fix unary overflow in parse_float64()
With 19 decimal digits, it is possible to obtain the exact value of `Int64.min`, which happens to be the only value that triggers an overflow with the unary minus operator.
2026-04-24 19:03:53 -07:00
Tim Kientzle bd67f95305 FP Parsing: Fix over-eager underflow check
An early check for underflow was a bit too aggressive, resulting in values that
would otherwise round up to the smallest subnormal failing to go through the
regular rounding logic.

Resolves #86462
Resolves rdar://167942063
2026-01-12 11:52:31 -08:00
Tim Kientzle e75a8c03e7 Fix parsing issues on 32-bit hosts
These were mostly bugs with code of the following form:
```
  if uint64Value < (... literal expression ...)
```
Swift's comparison operators allow their left- and right-hand sides to be of
different widths.  This in turn means that the literal expression above
typically gets typechecked by default as a plain `Int` or `UInt` expression.
In a number of cases, this led to truncation on platforms where `Int` is
not 64 bits.

In particular, this seems to fix tests on wasm32.
2025-12-12 07:16:59 -08:00
Tim Kientzle 2e56ce0b98 Minor perf tweak 2025-12-09 09:30:38 +00:00
Tim Kientzle 8393f0639c Minor perf tweak 2025-12-08 08:02:49 +00:00
Tim Kientzle fa0aa7506b Avoid un unnecessary bounds check 2025-12-08 07:39:09 +00:00
Tim Kientzle 2c9227e4c8 Update comments 2025-12-07 13:20:49 +00:00
Tim Kientzle 16920b200b Revert "Express the core parser functions as initializers"
After further thought, I realize that it makes more sense
to keep the public API in FloatingPointParsing.swift.gyb
(where we can consolidate the repetitive doc comments)
and have this as a purely internal set of service functions.

This reverts commit 7084ab8e6e.
2025-12-07 10:21:44 +00:00
Tim Kientzle 7084ab8e6e Express the core parser functions as initializers 2025-12-06 09:04:14 +00:00
Tim Kientzle f48aa4a627 Make Float16 support conditional on Swift 5.3 2025-12-06 09:04:14 +00:00
Tim Kientzle 09cad0dbcd Disable this code on 16-bit platforms 2025-12-06 09:04:14 +00:00
Tim Kientzle 7d5fff34fc Fix 16-bit build 2025-12-06 09:04:13 +00:00
Tim Kientzle c5ab343358 Fix the backwards-compatibility stubs 2025-12-06 09:04:13 +00:00
Tim Kientzle c8f12e69e2 Fix up some comments 2025-12-06 09:04:13 +00:00
Tim Kientzle 93eb82c9a3 [Embedded] Reimplement Float16/32/64 parsing in Swift
This reimplements the underlying support for `Float16(_:StringSlice)`,
`Float32(_:StringSlice)`, and `Float64(_:StringSlice)` in pure Swift,
using the same core algorithm currently used by Apple's libc.  Those
`StringSlice` initializers are in turn used by `Float16(_:String)`,
`Float32(_:String)`, and `Float64(_:String)`.

**Supports Embedded**: This fully supports Embedded Swift and
insulates us from variations in libc implementations.

**Corrects bugs in Float16 parsing**: The previous version of
`Float16` parsing called libc `strtof()` to parse to a 32-bit float,
then rounded to `Float16`. (This was necessary because float16
parsing functions are not widely supported in C implementations.)
This double-rounding systematically corrupted NaN payloads and
resulted in 1 ULP errors for certain decimal and hexadecimal inputs.
The new version parses `Float16` directly, avoiding these errors.

**Modest perforamnce improvement**:  The old version had to copy
the Swift string to construct a C string.  For inputs longer than
15 characters, this typically required a heap allocation, which added
up to 20% to the runtime.  The new version parses directly from a Swift
string, avoiding this copy and heap allocation.
2025-12-06 09:04:12 +00:00