Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RFC-1092 for support of System.Half #499

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions RFCs/RFC-1092-support-cli-half-type-as-float16.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# F# RFC FS-1092 - Support CLI half type as float16

The design suggestion [Support new CLI type: half type/float16](https://github.com/fsharp/fslang-suggestions/issues/909) has been marked "approved in principle".

This RFC covers the detailed proposal for this suggestion.

- [x] Approved in principle
- [x] [Suggestion](https://github.com/fsharp/fslang-suggestions/issues/909)
- [ ] [Implementation] tbd
- [x] Design Review Meeting(s) with @dsyme and others invitees: n/a
- [x] [Discussion](https://github.com/fsharp/fslang-design/issues/500)

# Summary

The runtime has added the `System.Half` which implements IEEE-754 binary-16 floating point. This proposal goes over the details of adding that type as an type alias to the language akin to how `float32` and `float` are available: that is, next to the type alias, casting functions, literals and utility functions.

# Motivation

The type `System.Half` is a new primitive type particularly targeted for high performance SIMD processing where the lesser precision is not a problem. The motivation is further explained [in the Runtime proposal](https://github.com/dotnet/runtime/issues/936).

# Detailed design

The types and functions in FSharp.Core will be extended with the following:

* Two type aliases, `half` and `float16` that map to `System.Half`.
* Two conversion functions named `float16` (compiled name `ToHalf`) and `half` as alias, with the following statically available overloads (open question: should we provide overloads for other primitives [than the BCL provides](https://docs.microsoft.com/en-us/dotnet/api/system.half?view=net-5.0)?)
* `double -> half`
* `float32 -> half`
* `string -> half`
* Add overloads to functions `double` and `float` for: `half -> double`
* Add overloads for functions `single` and `float32` for: `half -> float32`
* Add public let binding `nanh: half`, compiled name `NaNHalf`
* Add public let binding `infinityh: half`, compiled name `InfinityHalf`
* Make sure all arithmetic operators work when both arguments are `half`s.
* Make sure generic comparison for two `half` arguments map to `Half.GreaterThan` etc.
* Add a numeric literal postfix letter, `h`, to allow parsing of literals as `half` types (open question)

Example code:

```fsharp
// must be callable with half arguments
let add x y = x + y

// x is of type `half`
let x = half 34.56

// x is of type `half`
let x = 42.99h
```

# Drawbacks

If we don't do this, people could still use `System.Half` directly, but don't have good language support, like overloaded conversion functions and proper compilation to IL.
Copy link
Contributor

Choose a reason for hiding this comment

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

I would like to understand the current experience of using System.Half and see a comparison of what does and doesn't work when the user simply defines an alias type half = System.Half.

My belief is the experience won't be that bad but some conversions will be missing, as will a half function.

I don't know of anything that falls under the "proper compilation to IL" category.

We should be precise about the current experience.

Copy link
Member Author

Choose a reason for hiding this comment

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

@dsyme It's been a while, but the current experience is indeed not too bad. Though users do not have formatters in sprintf and the like, nor do they have any ability for creating constants. The latter might actually be made possible if we were to allow constants of any blittable type (???).

I doubt System.Half is widely used presently. It's main use case is in CUDA and AI programming.

While I'd like this feature (and Int128, for that matter), unless we find a way to support features from .NET 6.0 and up, I don't quite see this happening: #500 (comment).


# Alternatives

No alternatives are known.

# Compatibility

Please address all necessary compatibility questions:

* Is this a breaking change?
* No
* What happens when previous versions of the F# compiler encounter this design addition as source code?
* They continue to work
* What happens when previous versions of the F# compiler encounter this design addition in compiled binaries?
* Unless both binaries are compiled against .NET 5.0, this may lead to assembly loading errors.
* If this is a change or extension to FSharp.Core, what happens when previous versions of the F# compiler encounter this construct?
* We should take proper measures to allow FSharp.Core to be linked with other versions of .NET that do not have this type.


# Unresolved questions
Copy link
Member

Choose a reason for hiding this comment

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

The chief unresolved question for me is that because this type is only available in .NET 5 and higher, we'll need to understand the best way to expose the type alias. Referencing it as System.Half is fine as that will all work according to your environment. But since type abbreviations in FSharp.Core are ultimately orthogonal, we'll have to figure it out.

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree, I put that in the discussion thread too. For this and future dependencies on features added to net core or NetStandard, we need perhaps some bespoke way to implement that in FSharp.Core so that it can still be used interchangeably with older versions too.


1. Should we add an additional numeric literal suffix?
2. How can we ensure FSharp.Core can be used with this new type in .NET 5.0, but still link to older versions?
3. Should we add overloads like `half: int -> half` and `half: decimal -> half` even though `System.Half` does not define them?