math.h float_t and double_t not typedef'ed when FLT_EVAL_METHOD defined

Craig Howland
Thu Nov 22 10:31:00 GMT 2012

Yes, the manner in which math.h handles float_t and double_t is lacking, and 
yes, the solution is quite similar to what you list.  The problem is that the 
else case is tricky, when the value is not 0, 1, or 2.

I actually have an improved version of this part of the file as part of an 
overall math.h cleanup that I've been working on, but I can't presently make 
patches due to a CVS issue.  Here's what I presently have for comment.  (I last 
worked on this part 2 years ago, so maybe my comment about the autoconf version 
is no longer applicable, although it probably still is.)  Once I have the CVS 
issue ironed out, I can submit this.  There is one question on the approach we 
want to take for the aforementioned else.

The two approaches for unknown values are to default to something or to define 
nothing.  In the code below, you can see that I opted for the former, along with 
the reason for so doing.

/* FIXME:  FLT_EVAL_METHOD should somehow be gotten from float.h (which is hard,
  * considering that the standard says the includes it defines should not
  * include other includes that it defines) and that value used.  (This can be
  * solved, but autoconf has a bug which makes the solution more difficult, so
  * it has been skipped for now.)  */
#if !defined(FLT_EVAL_METHOD) && defined(__FLT_EVAL_METHOD__)
   #define __TMP_FLT_EVAL_METHOD
#endif /* FLT_EVAL_METHOD */
#if defined FLT_EVAL_METHOD
   #if FLT_EVAL_METHOD == 0
     typedef float  float_t;
     typedef double double_t;
    #elif FLT_EVAL_METHOD == 1
     typedef double float_t;
     typedef double double_t;
    #elif FLT_EVAL_METHOD == 2
     typedef long double float_t;
     typedef long double double_t;
     /* Implementation-defined.  Just make something up, as have no idea what
      * the implementation does (FP not being Newlib-related, but from the
      * compiler and/or hardware).  float and double will work, even if they do
      * not meet the intent of being most efficient.  */
     typedef float  float_t;
     typedef double double_t;
#if defined(__TMP_FLT_EVAL_METHOD)

Thoughts and comments on how to handle the if?  Even though I made the tentative 
choice of a default when I wrote this in 2010, my present inclination is that 
nothing should be defined so that such an implementation would have to put them 
in somehow for things which use them to work.  (It would be less of a mess if 
the standard had put float_t and double_t in float.h along with FLT_EVAL_METHOD.)


On 11/16/2012 06:34 AM, Jordy Potman wrote:
> Hi,
> I am using Newlib with a clang based compiler for our architecture.
> I think I have found an issue in Newlib's math.h.
> Newlib's math.h does not typedef float_t and double_t when
> FLT_EVAL_METHOD is defined.
> math.h lines 143-147:
> 143: #ifndef FLT_EVAL_METHOD
> 144: #define FLT_EVAL_METHOD 0
> 145: typedef float float_t;
> 146: typedef double double_t;
> 147: #endif /* FLT_EVAL_METHOD */
> Clang's float.h defines FLT_EVAL_METHOD (I think gcc's float.h does as
> well), which I think is correct according to section paragraph
> 8 of the C99 standard.
> Newlib's math.h defines the log2f function as a macro which uses
> float_t.
> math.h lines 354-357:
> 354: extern float log2f _PARAMS((float));
> 355: #if !defined(__cplusplus)
> 356: #define log2f(x) (logf (x) / (float_t) _M_LN2)
> 357: #endif
> This causes a compilation error if a program includes float.h before
> math.h and uses the log2f function:
> $ cat log2f_test.c
> #include<float.h>
> #include<math.h>
> float f(float a) {
>    return log2f(a);
> }
> $ xentium-clang -std=c99 -c log2f_test.c
> log2f_test.c:5:10: error: use of undeclared identifier 'float_t'; did
> you mean 'float'?
>    return log2f(a);
>           ^
> /home/potman/opt/xentium-tools-1.0.beta9-linux64/bin/../sysroots/default/include/math.h:359:31: note: expanded from
>        macro 'log2f'
> #define log2f(x) (logf (x) / (float_t) _M_LN2)
>                                ^
> 1 error generated.
> I have changed math.h lines 354-357 to the following in our
> implementation:
> #define FLT_EVAL_METHOD 0
> #endif /* FLT_EVAL_METHOD */
> #if FLT_EVAL_METHOD == 1
> typedef double float_t;
> typedef double double_t;
> #elif FLT_EVAL_METHOD == 2
> typedef long double float_t;
> typedef long double double_t;
> #else
> typedef float float_t;
> typedef double double_t;
> #endif
> This is my interpretation of how float_t and double_t should be
> typedef'ed depending on the value of FLT_EVAL_METHOD as is described in
> section 7.12 paragraph 2 of the C99 standard. However I am not a C99
> standard expert.
> Jordy

More information about the Newlib mailing list