Skip to content

Conversation

@tbkka
Copy link
Contributor

@tbkka tbkka commented Dec 2, 2025

This reimplements the underlying support for Float16(_:Substring), Float32(_:Substring), and Float64(_:Substring) in pure Swift, using the same fast algorithms currently used by Apple's libc. Those Substring initializers are in turn used by Float16(_:String), Float32(_:String), and Float64(_:String).

Supports Embedded: This fully supports both Embedded and non-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 performance improvement: The old version had to copy the Swift string to construct a C string. This often incurred 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.

@tbkka
Copy link
Contributor Author

tbkka commented Dec 2, 2025

@swift-ci Please test


#if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64))

@available(SwiftStdlib 5.3, *)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephentyrone Any thoughts on whether I can delete this entire function? Since it was public before, it's conceivable that someone was calling it directly, but no stdlib code ever called it.

@tbkka
Copy link
Contributor Author

tbkka commented Dec 2, 2025

@swift-ci Please test

@rauhul rauhul linked an issue Dec 2, 2025 that may be closed by this pull request
@rauhul rauhul added the embedded Embedded Swift label Dec 2, 2025
@rauhul rauhul moved this to In Progress in Embedded Swift Dec 2, 2025
@tbkka
Copy link
Contributor Author

tbkka commented Dec 3, 2025

@swift-ci Please test

3 similar comments
@tbkka
Copy link
Contributor Author

tbkka commented Dec 3, 2025

@swift-ci Please test

@tbkka
Copy link
Contributor Author

tbkka commented Dec 3, 2025

@swift-ci Please test

@tbkka
Copy link
Contributor Author

tbkka commented Dec 4, 2025

@swift-ci Please test

// Caveat: _swift_stdlib_strto{f,d,ld}_clocale() was called directly from inlineable
// code until Feb 2020 (commit 4d0e2adbef4d changed this), so they need to be
// exported with the same C-callable ABI for as long as we support code compiled
// with Swift 5.3.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a test calling the compatibility symbols directly, to avoid inattention-induced rot?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have the ABI checks to verify the symbols are still present, but you're right that it would be good to have something stronger.

@tbkka
Copy link
Contributor Author

tbkka commented Dec 4, 2025

@swift-ci Please test macOS

tbkka added 10 commits December 4, 2025 09:35
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.
Because these support functions used to be implemented in C, they could
be present on macOS x86_64, even though Float16 isn't supported
there otherwise.  With the new Swift implementation, we can't define
these functions on x86_64 macOS, so remove them from the expected list.
@tbkka tbkka force-pushed the tbkka-float-parsing branch from 06ce320 to 69857f4 Compare December 4, 2025 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

embedded Embedded Swift

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

Embedded Swift: Float Parsing

3 participants