Solved [Solved] System/Compiler support for denormal numbers.

Maelstorm

Well-Known Member

Reaction score: 132
Messages: 326

What standards does clang support? This is on FreeBSD 9.3-RELEASE #2 r270190 i386. I'm working on some floating point stuff and I ran into a problem. In /usr/include/machine/float.h, which includes on my platform /usr/include/x86/float.h, we have the following lines:

Code:
#if __ISO_C_VISIBLE >= 2011
#define FLT_TRUE_MIN    1.40129846E-45F /* b**(emin-p) */
#define FLT_DECIMAL_DIG 9               /* ceil(1+p*log10(b)) */
#define FLT_HAS_SUBNORM 1
#endif /* __ISO_C_VISIBLE >= 2011 */
When I run the command clang -dM -E - < /usr/include/machine/float.h, I get some very interesting output. The most interesting of this output though is the following:
Code:
#define __FLT_HAS_DENORM__ 1
#define __ISO_C_VISIBLE 1999
#define __STDC_VERSION__ 199901L
The way that I am interpreting this is that clang uses ISO C 1999 which is less than 2011 and so it does not include the subnormal/denormal float definitions. I find this strange since the compiler supports it by having __FLT_HAS_DENORM__ defined as true but the header file skips it. Additionally, in /usr/include/sys/cdefs.h, I found the following code:
Code:
#ifdef _POSIX_C_SOURCE
#if _POSIX_C_SOURCE >= 200809
#define __POSIX_VISIBLE         200809
#define __ISO_C_VISIBLE         1999
#elif _POSIX_C_SOURCE >= 200112
#define __POSIX_VISIBLE         200112
#define __ISO_C_VISIBLE         1999
#elif _POSIX_C_SOURCE >= 199506
#define __POSIX_VISIBLE         199506
#define __ISO_C_VISIBLE         1990
#elif _POSIX_C_SOURCE >= 199309
#define __POSIX_VISIBLE         199309
#define __ISO_C_VISIBLE         1990
#elif _POSIX_C_SOURCE >= 199209
#define __POSIX_VISIBLE         199209
#define __ISO_C_VISIBLE         1990
#elif _POSIX_C_SOURCE >= 199009
#define __POSIX_VISIBLE         199009
#define __ISO_C_VISIBLE         1990
#else
#define __POSIX_VISIBLE         198808
#define __ISO_C_VISIBLE         0
#endif /* _POSIX_C_SOURCE */
As one can see, 2011 isn't in there. Not sure if this is a bug or something else. I also tried using -std=c11 and it still doesn't work. I would like to not use the __ defines as those are system dependent. Any ideas?

EDIT: 1-OCT-2014
Changed title from "clang supported standards" to "System/Compiler support for denormal numbers" to better describe the issue.
Added SOLVED tag to title.
 

freethread

Well-Known Member

Reaction score: 32
Messages: 359

Re: clang supported standards

I'm not updated about C standards, also on CLANG web site there is no pages about C standards status, only for C++.

In the Language Extensions page two test macros are described to get C++11 and C11 compiler features: __has_feature and __has_extension. Hope this help.
 

kpa

Beastie's Twin

Reaction score: 1,805
Messages: 6,318

Re: clang supported standards

I'm not sure if this applies to your work but I do recall reading a discussion about (lack of) support for certain floating point functions in FreeBSD. This wiki page seems to be related:

https://wiki.freebsd.org/Numerics
 
OP
OP
Maelstorm

Maelstorm

Well-Known Member

Reaction score: 132
Messages: 326

System/Compiler support for denormal numbers.

I was able to work around the issue by analyzing what gcc and clang supported in regards to denormal or subnormal numbers. What is interesting though is that clang and gcc have different ideas as to what FLT_TRUE_MIN are.

Code:
/* XXX: This is to fix a problem where the compiler supports various features
   such as denormal/subnormal numbers, but the system environment doesn't. */
#ifdef __clang__

#if !defined(FLT_TRUE_MIN) && defined(__FLT_HAS_DENORM__)
#define FLT_TRUE_MIN    __FLT_DENORM_MIN__
#endif /* denormal float numbers */

#if !defined(DBL_TRUE_MIN) && defined(__DBL_HAS_DENORM__)
#define DBL_TRUE_MIN    __DBL_DENORM_MIN__
#endif /* denormal double numbers */

#if !defined(LDBL_TRUE_MIN) && defined(__LDBL_HAS_DENORM__)
#define LDBL_TRUE_MIN   __LDBL_DENORM_MIN__
#endif /* denormal long double numbers */

#endif /* clang-llvm */


#ifdef __GNUC__

#if !defined(FLT_TRUE_MIN) && defined(__FLT_HAS_DENORM__)
#define FLT_TRUE_MIN    __FLT_DENORM_MIN__
#endif /* denormal float numbers */

#if !defined(DBL_TRUE_MIN) && defined(__DBL_HAS_DENORM__)
#define DBL_TRUE_MIN    __DBL_DENORM_MIN__
#endif /* denormal double numbers */

#if !defined(LDBL_TRUE_MIN) && defined(__LDBL_HAS_DENORM__)
#define LDBL_TRUE_MIN   __LDBL_DENORM_MIN__
#endif /* denormal long double numbers */

#endif /* GNU C */
This way, if it's not defined in the system environment but the compiler supports it, then it is defined. If it's not supported at all, then it's not defined at all. But, if it is supported in the system environment, then the system definitions are left alone. It seems that this is a c2011 standard which is not supported in c1999. However, the hardware supports it, and this is a computer from 2001.
 
Top