[PATCH v3 2/3] Add default implementation of fenv.h and all methods

Howland, Craig D. - US via newlib newlib@sourceware.org
Thu Aug 8 03:24:00 GMT 2019


> From: newlib-owner@sourceware.org <newlib-owner@sourceware.org> on behalf of Brian Inglis <Brian.Inglis@SystematicSw.ab.ca>
> Sent: Wednesday, August 7, 2019 8:00 PM
> To: newlib@sourceware.org
> Subject: Re: [PATCH v3 2/3] Add default implementation of fenv.h and all methods
>
> On 2019-08-07 07:28, Joel Sherrill wrote:
> > On Wed, Aug 7, 2019 at 8:27 AM Howland, Craig D. via newlib wrote:
> >> On Wednesday, August 7, 2019 4:36 AM Corinna Vinschen wrote:
> >>> On Aug  6 14:13, Joel Sherrill wrote:
>
> Wouldn't it be clearer to conditionally define those constants based on some
> obviously fictional symbol e.g.
>
> #if FLOATING_POINT_EXCEPTIONS_SUPPORTED // replace by implementation symbol
> /*
>  * The following macros are to be defined if the respective exception is
>  * supported by the implementation, each with a unique bit mask:
>  *
>  *      FE_DIVBYZERO
>  *      FE_INEXACT
>  *      FE_INVALID
>  *      FE_OVERFLOW
>  *      FE_UNDERFLOW
>  *
>  * Other implementation-specific exceptions may be defined, and must start
>  * with FE_ followed by a capital letter.
>  *
>  * FE_ALL_EXCEPT must be defined as the logical OR of all exceptions.
>  */
> #define FE_DIVBYZERO 0x00000001
> #define FE_INEXACT   0x00000002
> #define FE_INVALID   0x00000004
> #define FE_OVERFLOW  0x00000008
> #define FE_UNDERFLOW 0x00000010
>
> #define FE_ALL_EXCEPT \
>         (FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW)
>
> /*
>  * The following macros are to be defined if the respective rounding direction
>  * is supported by the implementation via the fegetround() and fesetround()
>  * functions, each with a unique positive value.
>  *
>  *   FE_DOWNWARD
>  *   FE_TONEAREST
>  *   FE_TOWARDZERO
>  *   FE_UPWARD
>  *
>  * Other implementation-specific rounding modes may be defined, and must start
>  * with FE_ followed by a capital letter.
>  */
> #define FE_DOWNWARD        1
> #define FE_TONEAREST       2
> #define FE_TOWARDZERO      3
> #define FE_UPWARD          4
>
> #endif // FLOATING_POINT_EXCEPTIONS_SUPPORTED - replace by implementation symbol
>
> #define FE_ALL_EXCEPT 0      /* NONE SUPPORTED IN PLACEHOLDER TEMPLATE */
>
> >>>> +/*
> >>>> + * The following typedefs are required. See the C and POSIX standards
> >> for
> >>>> + * details:
> >>>> + *
> >>>> + *   fenv_t
> >>>> + *   fexcept_t
> >>>> + */
> >>>> +typedef size_t fenv_t;
> >>>> +typedef size_t fexcept_t;
>
> >>> While these types are defined, the above macros are not.  Wouldn't
> >>> it make sense to define all or nothing by default?
>
> >> The standards require the types to be defined, but the individual macros
> >> are to be defined only if supported by the implementation.  The
> >> default implementation being provided supports nothing, only
> >> returning error, so it is proper for them to not be defined.  But having
> >> them there commented out to serve as a template seems to be a good thing.
>
> > Quick reply. :)
> > This is the POSIX language:
> > "The *<fenv.h>* header shall define the following constants if and only if
> > the implementation supports the floating-point exception by means of the
> > floating-point functions *feclearexcept*(), *fegetexceptflag*(),
> > *feraiseexcept*(), *fesetexceptflag*() and *fetestexcept*().
> > Each expands to an integer constant expression with values such that
> > bitwise-inclusive ORs of all combinations of the constants result in
> > distinct values."
>
> --
> Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada
>
Each of the 5 shown exceptions and each of the 4 showns rounding methods are
individually optional, so implementations can define any or none of them.  So
someone making an implementation has to go and decide for each one, anyway--an
overall gate does not help there, and would be even one more thing that the
implementer needed to add at no apparent gain.  Notice also that for
exceptions, the standard-required FE_ALL_EXCEPT is basically the same as
FLOATING_POINT_EXCEPTIONS_SUPPORTED, except that it is created from the
individual defines--the reverse of a an overall exceptions gate.
(The standards are inconsistent in not providing a similar summary
for the rounding modes, although with the individual defines it is less a
requirement than a convenience.  And it is easily understood why they
did not, as the exception defines are required to be unique bits, while
the rounding defines only distinct values--ORing doesn't allow
individual identification of rounding mode defines.)

Additionally, the individual definitions are intended to be the gate in user
code, as they are only defined when supported.

#include <fenv.h>
...
#if FE_ALL_EXCEPT
  feclearexcept(FE_ALL_EXCEPT);
  #if DEBUG
    puts("Floating point exceptions exist");
  #endif
#endif
sin(arg);
#if defined(FE_INVALID)
  if(fetestexcept(FE_INVALID) == FE_INVALID)  printf("sin(%g) raised invalid exception", arg);
#endif

Notice also that there are two categories of things, so the single
FLOATING_POINT_EXCEPTIONS_SUPPORTED in the question is only half of it.
So even if there were to be an overall gate, there'd need to be two, one for
exceptions and one for rounding directions.

Craig



More information about the Newlib mailing list