fenv.h implementation questions

Bruce Evans bde at zeta.org.au
Sun Dec 21 23:47:12 PST 2003


On Sun, 21 Dec 2003, Steven G. Kargl wrote:

> Is the following a sufficient implementation of fenv.h?
> _fenv_t and _fexcept_t would be defined in machine/fenv.h,
> which I haven't implemented, yet.  I'm assuming that
> these may be architecture specific (e.g., endianness).

fenv_t and fexcept_t are very MD, and hopefully aren't needed
in more than 1 file, so they should be declared directly in
<machine/fenv.h>.

> SuSv3 states that the exception and rounding mode macros
> are to be defined *if and only if* the implementation
> supports them.  It also states that the function prototypes
> that I've include need to be specified.  However, why would
> we need to specify, say, fegetround(), if the implementation
> doesn't support control of the rounding mode?

C99 says the same.  I guess it is not expected that all rounding
modes are unsupported (after all, there should be a default
rounding mode and even if it is weird than it could be described
by a nonstandard FE_ macro).  fegetround() is needed if more than
2 rounding modes are supported and useful for avoiding special
cases if only 1 rounding mode is supported.  It is only not useful
if no rounding mode is supported (since then it should not be
called since it has no valid arg).

> Finally, how the heck do we implement the #pragma at the end?

Finish the relevant part of the C99 support in gcc, or wait for it.
I think this is a large task.  It would involve turning off certain
optimizations within the FENV_ACCESS ON region.

> #ifndef _FENV_H_
> #define _FENV_H_
>
> #include <sys/cdefs.h>
> #include <machine/fenv.h>
>
> typedef fenv_t _fenv_t;
> typedef fexcept_t _fexcept_t;
>
> #ifdef _EXCEPTIONS
> #define FE_DIVBYZERO	0x00000001	/* Divide by zero */
> #define FE_INEXACT	0x00000002	/* Inexact flag raised */
> #define FE_INVALID	0x00000004	/* Invalid operation */
> #define FE_OVERFLOW	0x00000008	/* Overflow */
> #define FE_UNDERFLOW	0x00000010	/* Underflow */
> #define FE_ALL_EXCEPT	0x0000001F	/* Bitwise-or of above flags */
> #endif /* _EXCEPTIONS */
>
> #ifdef _ROUNDING_MODES
> #define FE_DOWNWARD	0x00000020	/* Round downward */
> #define FE_TONEAREST	0x00000040	/* Round to nearest */
> #define FE_TOWARDZERO	0x00000080	/* Round towards zero */
> #define FE_UPWARD	0x00000100	/* Round upwards */
> #endif /* _ROUNDING_MODES */

These should probably all be MD.  It saves a negative amount of code to
use a common definition since larger code would be required to convert
between the MI bits and the MI bits.

>
> #define FE_DFL_ENV (fenv_t const *)

This needs to point to something.

>
> #if !defined(_FENV_INLINED_)
> __BEGIN_DECLS
> extern int feclearexcept(int);
> extern int fegetenv(fenv_t *);
> extern int fegetexceptflag(fexcept_t *, int);
> extern int fegetround(void);
> extern int feholdexcept(fenv_t *);
> extern int feraiseexcept(int);
> extern int fesetenv(const fenv_t *);
> extern int fesetexceptflag(const fexcept_t *, int);
> extern int fesetround(int);
> extern int fetestexcept(int);
> extern int feupdateenv(fenv_t *);
> __END_DECLS
> #endif /* !_FENV_INLINED_ */

I don't see much point in inlining these (like the i386 fp* versions).
Marcel pointed out that inline versions are good for backwards
compatibility (the library can be changed without affecting old interfaces),
but we don't need that for standard interfaces.

>
> #if 0
> /* XXX Need to implement the FENV_ACCESS pragma */
> #endif
>
> #endif /* _FENV_H_ */

Bruce


More information about the freebsd-standards mailing list