Thursday, April 7, 2011

Handling fpu exception on windows

I would like to handle fpu exception on windows, something like:

#include <math.h>
#include <fenv.h>
#include <stdio.h>

int main()
{
    double b = 0;
    int raised;
    feclearexcept (FE_ALL_EXCEPT);
    b /= 0;
    raised = fetestexcept (FE_OVERFLOW | FE_INVALID);
    if (raised & FE_OVERFLOW) { printf("over\n");}
    if (raised & FE_INVALID)  { printf("invalid\n");}

    return 0;
}

But on windows. I tried reading the MSDN, but the document is not clear at all. I want to do this with Visual Studio compilers, on both x86 and amd64 archs.

I am not interested in translating the exception in C++ - actually, I am not even interested in the FPU exception, only in knowing the FPU state after some computation, like the example above.

== edit ==

Ok, it looks like it is actually much simpler: using _clearfp is enough:

#include <math.h>
#include <float.h>
#include <stdio.h>

int main()
{
    double b = 0;
    int raised;
    raised = _clearfp();
    b /= 0;
    raised = _clearfp();
    if (raised & SW_INVALID)  { printf("invalid\n");}

    return 0;
}

Much better than dealing with exceptions, SEH and other non portable stuff :)

From stackoverflow
  • These functions are mandated by the standard, so you should have no problem in porting. What exact error are you hitting?

    David Cournapeau : It does not even compile - AFAIK, MS compilers do not have fenv.h, but have their own mechanism.
    dirkgently : For VS you'd have to rely on the pragma arul mentioned.
  • If it's Visual Studio, try putting in this line:

    #pragma   float_control (except, on)
    

    More about this here and here.

    EDIT:

    If you want to do this in plain C, you'll need to take a look at the structured exception handling (SEH).

    David Cournapeau : The two links are extremely unclear, unfortunately; I don't understand what float_control is supposed to do: translate the error into C++ exception ? I would like a pure C solution.
  • You can use _statusfp2() to retrieve the floating point status. Beware that 32-bit uses both FPU and SSE instructions. Some sample code:

    #include "stdafx.h"
    #include <float.h>
    #include <math.h>
    #include <assert.h>
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
      unsigned x86;
      unsigned sse;
      // Test zero-divide
      double d = 0;
      double v = 1 / d;
      _statusfp2(&x86, &sse);
      assert(x86 & _EM_ZERODIVIDE);
      // Test overflow
      v = pow(10, 310.0);
      _statusfp2(&x86, &sse);
      assert(sse & _EM_OVERFLOW);
      return 0;
    }
    
    David Cournapeau : thanks, this is exactly what I was looking for.

0 comments:

Post a Comment

Note: Only a member of this blog may post a comment.