Greetings,
I found out that C++ function "std::isfinite ()" is so slow, so I have decided to write my own function killing NAN's and/or INF's and turn them into zero. My code follows:
bool sanitize_number(long double& x) { MY_STATIC_ASSERT(sizeof(long double)==16,"sizeof(long double)!=16 !!!"); MY_STATIC_ASSERT(sizeof(unsigned long long)==8,"sizeof(unsigned long long)!=8 !!!"); MY_STATIC_ASSERT(sizeof(unsigned long long)*2==sizeof(long double),"sizeof(sizeof(unsigned long long)*2!==sizeof(long double) !!!"); #if __INTEL_COMPILER_BUILD_DATE > 20141022 // workaround for bug in ICC 14.0.3.202 Update 4 (package 237); as well as ICC 15.0 Update 1 unsigned long long lx=*(reinterpret_cast<const unsigned long long*>(&x)+0); unsigned long long hx=*(reinterpret_cast<const unsigned long long*>(&x)+1); lx|=(hx & 0x0000ffffffffffffLL); hx&=0x7fff000000000000LL; if((hx | lx)==0) { // zero return true; } else if(my_unlikely(hx==0)) { // subnormal x=0; return false; } else if(my_unlikely(hx==0x7fff000000000000LL)) { // NaN, +/-Inf x=0; return false; } #else double xx=x; if(!sanitize_number(xx)) { x=0; return false; } #endif return true; }
the macro "MY_STATIC_ASSERT" is as follows:
# define MY_STATIC_ASSERT(cond, msg) \ static_assert(cond, msg)
It is just and only a sanity check to ensure we are compiling for x64 target and "long double" is 128-bit wide float on x64 target. It works just fine. I use in MSVC compile option "/Qlong_double" to force "long double" being 128-bit float.
But I have problem, that my code is incorectly detecting NAN of INF 128-bit float above line "#else", so there is typecast to "double". This happens both in ICC 14 and ICC 15. Can anyone could help me to make this binary-provided ugly hack to call bool sanitize_number(long double& x)" just to zero the invalid/NAN/INF floating number?" Since I find that this hack is faster than call to "std::isfinite ()".
Where do I did a programming mistake?
TIA!