This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: math.h float_t and double_t not typedef'ed when FLT_EVAL_METHOD defined
- From: Jordy Potman <jordy dot potman dot recore at gmail dot com>
- To: Craig Howland <howland at LGSInnovations dot com>
- Cc: newlib at sourceware dot org
- Date: Tue, 20 Nov 2012 12:39:00 +0100
- Subject: Re: math.h float_t and double_t not typedef'ed when FLT_EVAL_METHOD defined
- References: <1353065645.2048.23.camel@himalia> <50A6E1E3.2030604@LGSInnovations.com>
Hi Craig,
Thanks for sharing your improved version of the math.h float_t and
double_t handling.
Maybe we can include a machine header in the implementation defined
case? For example:
...
#else
/* Implementation-defined. */
#include <machine/fltevaltypes.h>
#endif
...
With newlib/libc/include/machine/fltevaltypes.h:
/* Default implementation defined float_t and double_t types. */
#ifndef _MACHINE_FLTEVALTYPES_H
#define _MACHINE_FLTEVALTYPES_H
typedef float float_t;
typedef double double_t;
#endif
which can be overridden by providing
newlib/libc/machine/<machinename>/machine/fltevaltypes.h .
Jordy
On Fri, 2012-11-16 at 20:01 -0500, Craig Howland wrote:
> 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
> >