math.h float_t and double_t not typedef'ed when FLT_EVAL_METHOD defined
Craig Howland
howland@LGSInnovations.com
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 FLT_EVAL_METHOD __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;
#else
/* 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;
#endif
#endif
#if defined(__TMP_FLT_EVAL_METHOD)
#undef FLT_EVAL_METHOD
#endif
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.)
Craig
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 5.2.4.2.2 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:
>
> #ifndef FLT_EVAL_METHOD
> #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