[stdlib] Add default payload to Signaling NaN#2494
[stdlib] Add default payload to Signaling NaN#2494stephentyrone merged 3 commits intoswiftlang:masterfrom
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 |
There was a problem hiding this comment.
We can't use precondition() in the library, it won't work correctly. Please use _precondition().
|
@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.
|
test/1_stdlib/Float.swift
Outdated
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
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
inifinitybit pattern.CC: @stephentyrone
What the default payload should be?
1is reasonable?Before merging this pull request to apple/swift repository: