This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler implementation of isnan()

I am using an TMS320F2837xS cpu (C28x DSP core + FPU + CLA). I am trying to test floats for nan using isnan(). The macro implementation for this in math.h (compiler version 6.2.5 and 6.4.9) is defined as: isnan(x) ((x) != (x)). This is technically correct for nan's but it fails the test in the compiled code. I have looked at the assembly code that this produces and the code executes a CMPF32. In the instruction set manual (sprueo2b.pdf) the description for this instruction states that "NaN will be treated as infinity". If I change my code to test the float using isinf() then the test is true for a nan, but the definition for isinf() in math.h is comparing the float against +-INFINITY and INFINITY and NaN definitions differ in a binary sense. Is this the expected behavior? If this is the case why is the definition in math.h invalid?

  • Hi Ian

    I am going to move your question to the compiler forum for the experts there to comment.

    Regards
    Lori
  • The bottom line is that you can't reliably test for NaN on C28x when using FPU, and there's really no workaround. What we intend to do in the compiler to deal with this is still kind of an open question. In the case of the isnan macro, it's testing whether the value of the float is NaN, but since the hardware treats NaN as +Inf, the value isn't "really" a NaN, it's +Inf, so it's reasonable that isnan would return false for NaN on this hardware. So yes, the current definition of isnan is intended and expected for C28x+FPU. It is conceivable that we might in the future add a mode where the compiler adds extra code to handle special values like NaN, denormals, and negative zero even when the hardware doesn't, but this would necessarily slow down the program, so it's unclear what the right answer is.
  • So currently, the implementation of  isinf() returns true for a NaN (because the FPU HW is treating NaN as +Inf in the CMPF32 instruction). Is it reasonable to assume this will remain true with the current HW and future compiler implementations? ie is a suitable workaround (albeit confusing)?

    So a macro defined as:

    #define ISNAN(x) (isinf(x) || isnan(x))

    would return true for the state of the compiler/HW now and in the future where either the compiler or the HW change to properly handle NaN. This assumes that isinf() does not change independently of isnan().

  • To be honest, I don't know. I doubt the hardware will change, so the question is whether we'll have the compiler add the extra code to handle NaN. I'd rather expect that inertia would keep the status quo, which is that you simply can't reliably test for NaN.

    Your proposed macro isn't exactly the same as IEEE isnan because it will return true for +Inf. You might consider instead using the C99 macro isnormal