Kenobi
Kenobi

Reputation: 423

Catch Nan and Inf in Windows C++

I painfully learned today that Nan and Inf have serious side issues. Did you know for example that sqrtf(NaN) is more than 15 times slower and sqrtf(-1) is 30 times slower (!!) than sqrtf(10.123132) - which is on its own a quite slow, floating point calculation!? You calculate rubbish, need ridiculous amounts of time for it and don't even realize it.

Ok, under Linux you can catch Nan and Inf bugs by throwing an exception when they occur:

#include <fenv.h> 
feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);

How could you achieve that under Windows?

EDIT: the Benchmarking code:

float a,b;
a = 1.0 / 0;   //inf
a = -10;         //also nice
long c=0;
long time = SDL_GetTicks();

for (long i=1;i<=1000000;i++) {
   b=sqrt(a); 
}

ostringstream Help; Help << SDL_GetTicks()-time;

//RESULT SHEET
//sqrt(1): 21ms
//sqrt(10): 21ms
//sqrt(10.123): 20ms
//sqrt(-10);   390ms
//sqrt(+-NaN): 174ms
//sqrt(inf):  174

Upvotes: 8

Views: 2663

Answers (2)

Henning
Henning

Reputation: 11

For me (only) the _controlfp approach worked, I used the "safe" implementation, namely:

 unsigned int current_word = 0; 
 _controlfp_s(&current_word, _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM); // raise exception on NaN (0xF)

the #pragma and /fp:except did not have any (/the desired) effect in my code (which consists of C code integrated into a C++ project).

Or, shorter - just kick out the _EM_INVALID flag to make NaN raise exception:

unsigned int current_word = 0; 
_controlfp_s(&current_word, 0, _EM_INVALID); // raise exception on NaN (set 0x10 bit to false)

Upvotes: 1

Nate Hekman
Nate Hekman

Reputation: 6657

If you're using Visual Studio, you can turn on floating point exceptions using the /fp:except option. See http://msdn.microsoft.com/en-us/library/e7s85ffb.aspx.

The equivalent in code is #pragma float_control( except, on ). See http://msdn.microsoft.com/en-us/library/45ec64h6(v=vs.110).aspx.

At runtime you can use something like _controlfp( _MCW_EM, _MCW_EM ). See http://msdn.microsoft.com/en-us/library/vstudio/e9b52ceh(v=vs.110).aspx.

Upvotes: 5

Related Questions