fenv.h standard header

G

Gregory Pietsch

Hello comp.lang.c enthusiasts,

Once while in a fit of pique, I thought I'd pull a Plauger. I have come
up with an implementation of the functions declared in the standard C99
header fenv.h. I thought I'd post them and get some constructive
criticism from this crowd of pedants.

First, the fenv.h header itself:

/* fenv standard header */
#ifndef _FENV
#define _FENV
/* typedefs */
typedef int fexcept_t;
typedef struct {
fexcept_t _FE_status_flags;
int _FE_rounding_direction;
} fenv_t;
/* floating-point exception constants */
#define FE_DIVBYZERO 0x01
#define FE_INEXACT 0x02
#define FE_INVALID 0x04
#define FE_OVERFLOW 0x08
#define FE_UNDERFLOW 0x10
#define FE_ALL_EXCEPT 0x1F
/* rounding constants */
#define FE_DOWNWARD 1
#define FE_TONEAREST 2
#define FE_TOWARDZERO 3
#define FE_UPWARD 4
/* default and current floating-point environments */
#define FE_DFL_ENV _FE_default_envp
extern const fenv_t *_FE_default_envp;
extern fenv_t _FE_current;
/* function prototypes */
#ifdef __cplusplus
extern "C"
{
#endif
int feclearexcept (int);
int fegetexceptflag (fexcept_t *, int);
int feraiseexcept (int);
int fesetexceptflag (const fexcept_t *, int);
int fetestexcept (int);
int fegetround (void);
int fesetround (int);
int fegetenv (fenv_t *);
int feholdexcept (fenv_t *);
int fesetenv (const fenv_t *);
int feupdateenv (const fenv_t *);
#ifdef __cplusplus
};
#endif
#endif /* _FENV */
/* END OF FILE */

Then, the implementation:

/* fe_constants.c - constants defined in fenv.h
AUTHOR: Gregory Pietsch
*/
#include <fenv.h>
fenv_t _FE_current = { 0, 3 };
fenv_t _FE_default_env = { 0, 3 };
const fenv_t *_FE_default_envp = &_FE_default_env;
/* END OF FILE */

/* feclearexcept.c - clear floating-point exception
AUTHOR: Gregory Pietsch
*/
#include <fenv.h>
int (feclearexcept) (int excepts)
{
if (excepts)
_FE_current._FP_status_flags &= ~excepts;
return 0;
}
/* END OF FILE */

/* fegetenv.c - get current floating-point environment
AUTHOR: Gregory Pietsch
*/
#include <fenv.h>
int (fegetenv) (fenv_t * envp)
{
if (envp == 0)
return 1;
/* save current FPE */
envp->_FP_status_flags = _FE_current._FP_status_flags;
envp->_FP_rounding_direction = _FE_current._FP_rounding_direction;
return 0;
}
/* END OF FILE */

/* fegetexceptflag.c - get floating-point status flags
AUTHOR: Gregory Pietsch
*/
#include <fenv.h>
int (fegetexceptflag) (fexcept_t * flagp, int excepts)
{
if (flagp == 0)
return 1;
*flagp = (*flagp & ~excepts) | (_FE_current._FP_status_flags &
excepts);
return 0;
}
/* END OF FILE */

/* fegetround.c - get current rounding direction
AUTHOR: Gregory Pietsch
*/
#include <fenv.h>
int (fegetround) (void)
{
return _FE_current._FP_rounding_direction;
}
/* END OF FILE */

/* feholdexcept - save current floating-point environment
AUTHOR: Gregory Pietsch
*/
#include <fenv.h>
#include <signal.h>
int (feholdexcept) (fenv_t * envp)
{
if (envp == 0)
return 1;
/* save current FPE */
envp->_FP_status_flags = _FE_current._FP_status_flags;
envp->_FP_rounding_direction = _FE_current._FP_rounding_direction;
/* clear FP status flags */
_FE_current._FP_status_flags = 0;
/* install a continue on FP exceptions mode */
signal (SIGFPE, SIG_IGN);
return 0;
}
/* END OF FILE */

/* feraiseexcept.c - raise floating-point exception
AUTHOR: Gregory Pietsch
*/
#include <fenv.h>
#include <signal.h>
int (feraiseexcept) (int excepts)
{
_FE_current._FP_status_flags |= excepts;
raise (SIGFPE);
return 0;
}
/* END OF FILE */

/* fesetenv.c - set current floating-point environment
AUTHOR: Gregory Pietsch
*/
#include <fenv.h>
int (fesetenv) (const fenv_t * envp)
{
if (envp == 0)
return 1;
/* establish current FPE */
fesetexceptflag (&(envp->_FP_status_flags), FE_ALL_EXCEPT);
return fesetround (envp->_FP_rounding_direction);
}
/* END OF FILE */

/* fesetexceptflag.c - set floating-point status flags
AUTHOR: Gregory Pietsch
*/
#include <fenv.h>
int (fesetexceptflag) (const fexcept_t * flagp, int excepts)
{
if (flagp == 0)
return 1;
_FE_current._FP_status_flags =
(*flagp & excepts) | (_FE_current._FP_status_flags & ~excepts);
return 0;
}
/* END OF FILE */

/* fesetround.c - set current rounding direction
AUTHOR: Gregory Pietsch
*/
#include <fenv.h>
int (fesetround) (int round)
{
if (round >= 1 && round <= 4)
{
_FE_current._FP_rounding_direction = round;
return 0;
}
else
return 1;
}
/* END OF FILE */

/* fetestexcept.c - test floating-point exception flags
AUTHOR: Gregory Pietsch
*/
#include <fenv.h>
int (fetestexcept) (int excepts)
{
return (_FE_current._FP_status_flags & excepts);
}
/* END OF FILE */

Thanks in advance, Gregory Pietsch
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,815
Messages
2,569,702
Members
45,492
Latest member
juliuscaesar

Latest Threads

Top