In GLSL, what is the difference between isnan(x) and !(x == x)?

  • $\begingroup$ You mean, besides the fact that one of these is self-explanatory and the other appears to be gibberish? $\endgroup$ – Nicol Bolas Apr 25 '19 at 13:42
  • $\begingroup$ @NicolBolas comparison with self is the usual way to test for nan with standard conforming floats and glsl is, as far as I know, required to abide by them. Therefore I consider adding another function as superfluous (and confusing), unless (or especially if) it has a different behavior. $\endgroup$ – Tomas Apr 25 '19 at 14:49
  • $\begingroup$ "Usual" is in the eye of the beholder. C99 has isnan; C++11 has std::isnan. Java has Java.lang.Double.isNan. C# has Double.IsNan. IEEE-754 even has a specific predicate called isNaN. It seems to me that those relying on !(x==x) are due to using standard libraries that are deficient, not because it is "usual". An explicit function is always easier to understand than an idiom that must be learned. $\endgroup$ – Nicol Bolas Apr 25 '19 at 14:57
  • $\begingroup$ I did not know that such functions were so common. Thanks for mentioning them. Can I conclude that the behavior is indeed the same? By one's personal experience, is it possible that the two methods behave differently on some devices? $\endgroup$ – Tomas Apr 25 '19 at 15:09

IEEE-754 defines the isNaN property, which determines if a value is NaN. However, it is also defined to be a non-signaling operation; calling isNaN on an sNaN will never result in a signaled failure. By contrast, equality testing may signal when given sNaN values.

Now, GLSL explicitly states that signaling doesn't matter:

Support for signaling NaNs is not required and exceptions are never raised.

But of course, there's also the fact that isnan is a vector function, while !(x == x) only works on scalars. So if you want to test if any of the elements of a vec3 are NaN, you can do any(isnan(some_vec)), while the equality-testing equivalent would be even more obtuse and verbose: any(not(equal(some_vec, some_vec))).

And all of that ignores the simple usability reasons for having isnan. !(x == x) is an idiom which must be learned, while isnan is an easily looked up function whose name tells you want it does. After all, most users of floats tend to forget about NaN, so such an expression seems like a tautology, while "isnan" explicitly reminds such people that NaNs are a real thing and they are reading code where that fact is important.

Also, as previously stated, isNaN is a property defined by IEEE-754. It is also a function provided by the standard libraries of C99, C++11, Java, C#, Swift, Go, JavaScript, and I can keep going, but I think my point is clear.

| improve this answer | |
  • $\begingroup$ Great! So other languages actually have a difference between the two approaches. And glsl has the function just to mimic those languages, even if there is no difference (apart from the readability point). Thanks for the explanation :D $\endgroup$ – Tomas Apr 25 '19 at 15:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.