Does x.isNaN == (x != x)?

Examining performance in Instruments, I found a hot spot calling x.isNaN, and timing showed a significant improvement in a performance-sensitive section replacing that with x != x.

Is there any difference if nothing creates signalling NaNs?

Does anything in Swift create signalling NaNs?

The specific code was in an interval value type, replacing
var isNaN: Bool { min.isNaN || max.isNaN }
with
var isNaN: Bool { min != min || max != max }

I encountered this tracking down a performance problem in a generic function which did not inline Interval.isNaN when specialized on Interval. Separately, how can I encourage the compiler to inline Interval.isNaN in the specialization?

I can't answer the question, but I'll link the implementation of isNaN for the curious:

1 Like

Thank you. That "fixes" the issue with it not being inlined in the specialization. Though, as discussed in When should both @inlinable and @inline(__always) be used? - #2 by scanon, I need to consider whether the particular test case I'm looking at is representative or whether the code expansion of forcing inline will hurt performance elsewhere.

Yeah n != n will generate a UCOMISD instruction, which signals for SNANs. It exactly matches what Clang and GCC produce using isnan from math.h, with -fsignaling-nans (I don't think GCC actually supports it - really, isnan shouldn't signal).

Swift does a lot more work, but doesn't use any FP instructions so correctly doesn't signal.

IIRC, no normal math operations should ever produce a signalling NaN. It should always be something the user explicitly creates.

2 Likes

Correct, sNaN cannot be the result of any floating-point operation except for one that explicitly constructs a sNaN.

2 Likes
Terms of Service

Privacy Policy

Cookie Policy