Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7942 Discussions

Anyone is guru in IEEE 128-bit float for x64 AVX target helping me?

Marian_M_
Beginner
611 Views

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!

0 Kudos
9 Replies
Marian_M_
Beginner
611 Views

I forgot to mention "my_ulikely()" and "my_likely()" they are as follows:

#ifndef my_likely
#   if defined(__GNUC__) || defined(__INTEL_COMPILER)
#       define my_likely(x)     __builtin_expect(!!(x),1)
#       define my_unlikely(x)   __builtin_expect(!!(x),0)
#   else
#       define my_likely(x)     (x)
#       define my_unlikely(x)   (x)
#   endif
#endif

TIA!

0 Kudos
Marián__VooDooMan__M
New Contributor II
611 Views

I am sorry, I have used my older login, this is me again. I made a typo, the correct is:

"But I have problem, that my code is incorectly detecting NAN OR INF 128-bit float above line "#else".

TIA!

0 Kudos
TimP
Honored Contributor III
611 Views

According to my understanding, icl Qlongdouble option  by itself supports 80 bit data format without library support.  I wouldn't expect arch avx support for long double  in any compiler.  Icl may include some unsupported 128 bit long double features not necessarily compatible with your unspecified msvc version. Icl may not be best choice for work with long double.

0 Kudos
Marián__VooDooMan__M
New Contributor II
611 Views

Tim Prince wrote:

According to my understanding, icl Qlongdouble option  by itself supports 80 bit data format without library support.

but I am using Intel compiler with option "/Qlongdouble" for x64 target application, so "sizeof(long double)==16".

Tim Prince wrote:

I wouldn't expect arch avx support for long double  in any compiler.  Icl may include some unsupported 128 bit long double features not necessarily compatible with your unspecified msvc version. Icl may not be best choice for work with long double.

So I would expect for ICC x64 target to accept "sizeof(long double)==16" even in my MSVC 12 (2013), since ICC is "so called" replacement for MSVC semantics (and binary compatibility for "long double").

0 Kudos
Marián__VooDooMan__M
New Contributor II
611 Views

I mean binary compatibility for ICC x64 128-bit long double, not binary compatibility with MSVC, where "long double" is poorly 80-bit wide.

0 Kudos
TimP
Honored Contributor III
611 Views

sizeof tells how many bytes are used including padding.  You're correct that 80 bit long double is normally padded out to 16 bytes in x86_64. I still think you're in for trouble if you treat that as a true 128 bit data type, but maybe I'm missing your point.

0 Kudos
Marián__VooDooMan__M
New Contributor II
611 Views

I am sure it is 128-bit wide (i.e. 16 bytes) when option "/Qlongdouble" is used with x64 target. Without this option, it is 80-bit wide as it is in MSVC. Disadvantage of this option is that e.g. you cannot use "<<" operator in "stringstream" and friends, or "printf()" and friends, since you are calling MSVC's CRT library, so you need to cast it down to "double" first, in this case, when passing "long double".to CRT/STL library.

0 Kudos
Bernard
Valued Contributor I
611 Views

MSVC will cast down to 64-bit double primitive type even 80-bit long double type.

http://msdn.microsoft.com/en-us/library/9cx8xs15.aspx

0 Kudos
Bernard
Valued Contributor I
611 Views

There is no HW support for 128-bit FP primitive type on Intel CPU's.

0 Kudos
Reply