Skip to content

[stdlib] [SE-0067] Implement generic conversions to floating point #13782

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

Merged
merged 2 commits into from
Jan 8, 2018
Merged

[stdlib] [SE-0067] Implement generic conversions to floating point #13782

merged 2 commits into from
Jan 8, 2018

Conversation

xwu
Copy link
Collaborator

@xwu xwu commented Jan 6, 2018

The following initializers, approved in SE-0067, are absent from currently shipping floating-point protocols

protocol FloatingPoint {
  // ...
  /// The closest representable value to the argument.
  init<Source: Integer>(_ value: Source)

  /// Fails if the argument cannot be exactly represented.
  init?<Source: Integer>(exactly value: Source)
  // ...
}

protocol BinaryFloatingPoint {
  // ...
  /// `value` rounded to the closest representable value.
  init<Source: BinaryFloatingPoint>(_ value: Source)

  /// Fails if `value` cannot be represented exactly as `Self`.
  init?<Source: BinaryFloatingPoint>(exactly value: Source)
  // ...
}

In this PR, the missing initializers are added to their respective protocols, adjusted for revised integer protocol names and furnished with updated documentation. Default implementations for all of the above initializers are provided for BinaryFloatingPoint, and tests for those default implementations are included.

Some considerations

The default implementations provided here are not unnecessarily inefficient, but they are orders of magnitude slower than non-generic conversion initializers. For performance (and backwards compatibility) reasons, the non-generic conversion initializer requirements are maintained.

No default implementation is provided for init<T : BinaryInteger>(_: T) or init?<T : BinaryInteger>(exactly: T) on FloatingPoint itself. They are technically possible to implement (by serial division of the magnitude by powers of radix, calling init(_: UInt64) at each iteration), but they would be very slow. Although technically source-breaking without such default implementations, no first-party type conforms to FloatingPoint but not BinaryFloatingPoint (Foundation.Decimal does not conform to FloatingPoint), and no Swift decimal types are found among searchable open-source projects. Any hypothetical decimal type that conforms to FloatingPoint today is already required to implement the logic necessary to convert from binary integers, and efficient implementation of the new requirement would therefore be trivial.

Heterogeneous comparison methods approved in SE-0067 and still commented out have not been added in this PR. It could be added in a distinct PR, but such a move may or may not be wise at the moment. First, implicit generic conversions will incur the performance penalty discussed above. Second, the issue remains unresolved regarding comparison to a literal in generic contexts defaulting to heterogeneous comparison. Third, as noted in the commented-out code, the implementation of these heterogeneous comparison methods is not fully correct, although it is serviceable for built-in types.

@xwu
Copy link
Collaborator Author

xwu commented Jan 6, 2018

@moiseev
Copy link
Contributor

moiseev commented Jan 7, 2018

@swift-ci Please test

@swiftlang swiftlang deleted a comment from swift-ci Jan 7, 2018
@swiftlang swiftlang deleted a comment from swift-ci Jan 7, 2018
@xwu
Copy link
Collaborator Author

xwu commented Jan 7, 2018

@moiseev Sorry, one more time. After testing everything, I moved the default implementations into the wrong extension (FloatingPoint instead of BinaryFloatingPoint). 😞

@CodaFi
Copy link
Contributor

CodaFi commented Jan 7, 2018

@swift-ci please test

@swiftlang swiftlang deleted a comment from swift-ci Jan 7, 2018
@swiftlang swiftlang deleted a comment from swift-ci Jan 7, 2018
@xwu
Copy link
Collaborator Author

xwu commented Jan 7, 2018

How interesting! Signaling NaN gets automagically quieted on iOS but not macOS or Linux (or even the iOS simulator). Both behaviors are permissible per IEEE, but this must originate from differences in whether or not the value is quieted before its bit pattern is accessed, so I'd better rework some code.

Edit: Now ready to go.

@CodaFi
Copy link
Contributor

CodaFi commented Jan 7, 2018

@swift-ci please smoke test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants