-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
[stdlib] Add default payload to Signaling NaN #2494
Conversation
Or we could do this?: public static var signalingNaN: ${Self} {
return ${Self}(nan: 0, signaling: true)
}
public init(nan payload: RawSignificand, signaling: Bool) {
// We use significandBitCount - 2 for NaN payload.
precondition(payload < ${Self}._quietNaNMask >> 1,
"NaN payload is not encodable.")
var significand = payload
significand |= ${Self}._quietNaNMask >> (signaling ? 1 : 0)
self.init( ... )
} FWIW, C++
|
@swift-ci Please test and merge. |
@rintaro |
@@ -459,7 +459,13 @@ extension ${Self}: BinaryFloatingPoint { | |||
precondition(payload < ${Self}._quietNaNMask, | |||
"NaN payload is not encodable.") | |||
var significand = payload | |||
if !signaling { significand |= ${Self}._quietNaNMask } | |||
if signaling { | |||
precondition(payload != 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't use precondition()
in the library, it won't work correctly. Please use _precondition()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#2504, thank you for the info :)
@rintaro Could you take a look at the test failure? |
@gribozavr I'm looking into it, and will fix it. @stephentyrone is also working in this area now? |
I'm struggling to figure out the problem. --- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -191,7 +191,9 @@ extension ${Self}: BinaryFloatingPoint {
}
public init(bitPattern: UInt${bits}) {
+ print("bitPattern1: " + String(bitPattern, radix: 2))
self.init(_bits: Builtin.bitcast_Int${bits}_FPIEEE${bits}(bitPattern._value))
+ print("bitPattern2: " + String(self.bitPattern, radix: 2))
}
@available(*, deprecated, message: "Use the .bitPattern property instead.")
@@ -230,6 +232,7 @@ extension ${Self}: BinaryFloatingPoint {
self.init(bitPattern: sign << ${RawSignificand}(signShift) |
exponent << ${RawSignificand}(${Self}.significandBitCount) |
significand)
+ print("bitPattern3: " + String(self.bitPattern, radix: 2))
}
public var isCanonical: Bool { calling
calling
It looks like, on |
I confirmed with C++, Xcode7, iPhone 4s simulator: void printme(void *c, size_t n) {
// ... print bit pattern ...
}
float gen_snan() {
float a = std::numeric_limits<float>::signaling_NaN();
printme(&a, sizeof(a));
return a;
}
void print_snan() {
float a = gen_snan();
printme(&a, sizeof(a));
} output:
Maybe, we cannot support Found this Stackoverflow QA: |
0334325
to
71b906c
Compare
c645426
to
aa8bbae
Compare
Or it will have inifinity bit pattern.
aa8bbae
to
88df846
Compare
Updated the patch.
|
@@ -222,13 +222,24 @@ func checkQNaN(_ qnan: TestFloat) { | |||
_precondition(qnan.floatingPointClass == .quietNaN) | |||
} | |||
|
|||
func checkSNaN(_ snan: TestFloat) { | |||
checkNaN(snan) | |||
// FIXME: i386 doesn't fully support signaling NaN. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME
is a bit misleading here; i386 cannot fully support signaling NaN without a massive change to the calling conventions (because loading a Float or Double sNaN to x87 always signals invalid and quiets the NaN). The comment should read something more like:
// sNaN cannot be fully supported on i386.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do own Swift's calling convention. If it were worth it, we could consider changing the convention, for Float80 on x86_64 at least, to pass x87 floats by memory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On May 13, 2016, at 12:10 PM, Joe Groff notifications@github.com wrote:
In test/1_stdlib/Float.swift #2494 (comment):
@@ -222,13 +222,24 @@ func checkQNaN(_ qnan: TestFloat) {
_precondition(qnan.floatingPointClass == .quietNaN)
}+func checkSNaN(_ snan: TestFloat) {
- checkNaN(snan)
+// FIXME: i386 doesn't fully support signaling NaN.
We do own Swift's calling convention. If it were worth it, we could consider changing the convention, for Float80 on x86_64 at least, to pass x87 floats by memory.
It doesn’t effect Float80 load/store, only Float and Double[*], so there’s no problem on x86_64.
The problem is only on i386, and only for Float and Double. If we wanted to fix it, we would want to return them in xmm0 instead of fp(0).
[*] The history here is interesting. x87 originally did not have load/store of 80-bit values, only 32b and 64b, which were extended to 80b on load and rounded on store. When 80b load/store were added, they were the widest path to memory, so folks wanted to use it for memcpy, which meant that it could not change the values (and hence could not quiet signaling NaNs).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fractal complexity of x86 never ceases to amaze. If we're willing to assume SSE2, returning in xmm registers on i386 would be a nice improvement…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, it ends up being a ~30% perf win for smallish math functions. The only question is how much anyone cares about i386.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apple, maybe not so much, but there are still brand-new 32-bit Windows machines being sold today…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead, use `_quietNaNMask >> 1` as the payload. That is, we use only significandBitCount - 2 bits for NaN payload.
88df846
to
58c7f59
Compare
@swift-ci Please test |
@rintaro Thanks for following-up with this. |
LGTM, thanks @rintaro @stephentyrone! |
* [stdlib] Add default payload to Signaling NaN Or it will have inifinity bit pattern. * [stdlib] Skip isSignaling test on i386 arch see: #2494 * [stdlib] Allow 0 payload for signaling NaN Instead, use `_quietNaNMask >> 1` as the payload. That is, we use only significandBitCount - 2 bits for NaN payload.
What's in this pull request?
Or it will have
inifinity
bit pattern.CC: @stephentyrone
What the default payload should be?
1
is reasonable?Before merging this pull request to apple/swift repository: