148 lines
3.9 KiB
C
148 lines
3.9 KiB
C
/***
|
|
*fenv.h - definitions and declarations for floating point environment library
|
|
*
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
*
|
|
*Purpose:
|
|
* This file contains constant definitions and external subroutine
|
|
* declarations for the floating point environment subroutine library.
|
|
*
|
|
* [Public]
|
|
*
|
|
****/
|
|
|
|
#pragma once
|
|
|
|
#ifndef _FENV
|
|
#define _FENV
|
|
|
|
#include <float.h>
|
|
|
|
/*
|
|
* Currently, all MS C compilers for Win32 platforms default to 8 byte
|
|
* alignment.
|
|
*/
|
|
#pragma pack(push,_CRT_PACKING)
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
#if !defined(_M_CEE) || defined(_CRTBLD)
|
|
|
|
typedef unsigned long fexcept_t;
|
|
typedef struct fenv_t
|
|
{
|
|
unsigned long _Fe_ctl, _Fe_stat;
|
|
} fenv_t;
|
|
|
|
#define FE_INEXACT _SW_INEXACT /* _EM_INEXACT 0x00000001 inexact (precision) */
|
|
#define FE_UNDERFLOW _SW_UNDERFLOW /* _EM_UNDERFLOW 0x00000002 underflow */
|
|
#define FE_OVERFLOW _SW_OVERFLOW /* _EM_OVERFLOW 0x00000004 overflow */
|
|
#define FE_DIVBYZERO _SW_ZERODIVIDE /* _EM_ZERODIVIDE 0x00000008 zero divide */
|
|
#define FE_INVALID _SW_INVALID /* _EM_INVALID 0x00000010 invalid */
|
|
|
|
#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
|
|
|
|
_CRTIMP int __cdecl fegetenv(_Inout_ fenv_t *);
|
|
_CRTIMP int __cdecl fesetenv(_In_ const fenv_t *);
|
|
_CRTIMP int __cdecl feclearexcept(_In_ int);
|
|
_CRTIMP int __cdecl feholdexcept(_Inout_ fenv_t *);
|
|
_CRTIMP int __cdecl fetestexcept(_In_ int);
|
|
_CRTIMP int __cdecl fegetexceptflag(_Inout_ fexcept_t *, _In_ int);
|
|
_CRTIMP int __cdecl fesetexceptflag(_In_ const fexcept_t *, _In_ int);
|
|
|
|
__declspec(selectany) extern const fenv_t _Fenv0 = {0, 0};
|
|
|
|
#define FE_DFL_ENV (&_Fenv0)
|
|
|
|
#endif /* !defined(_M_CEE) || defined(_CRTBLD) */
|
|
|
|
#define FE_TONEAREST 0x0000
|
|
#define FE_UPWARD 0x0100
|
|
#define FE_DOWNWARD 0x0200
|
|
#define FE_TOWARDZERO 0x0300
|
|
|
|
#define FE_ROUND_MASK 0x0300
|
|
|
|
_CRTIMP int __cdecl fegetround(void);
|
|
_CRTIMP int __cdecl fesetround(_In_ int);
|
|
|
|
#if !defined(_M_CEE) && !defined(_CRTBLD)
|
|
|
|
/*
|
|
* feraiseexcept is inline in this header so that it will be compiled with
|
|
* the /arch setting specified in the consuming application, rather than the
|
|
* /arch:IA32 setting which is the default for the CRT library itself.
|
|
*
|
|
* feupdateenv is inline because it calls feraiseexcept.
|
|
*/
|
|
__inline int __CRTDECL feraiseexcept(_In_ int _Except)
|
|
{
|
|
#define __DBL_BIG 1e+300 /* may raise inexact too */
|
|
|
|
static struct
|
|
{
|
|
int _Except_Val;
|
|
double _Num, _Denom;
|
|
} const _Table[] =
|
|
{ /* raise exception by evaluating num / denom */
|
|
{FE_INVALID, 0.0, 0.0},
|
|
{FE_DIVBYZERO, 1.0, 0.0},
|
|
{FE_OVERFLOW, __DBL_BIG, 1.0 / __DBL_BIG},
|
|
{FE_UNDERFLOW, 1.0 / __DBL_BIG, __DBL_BIG},
|
|
{FE_INEXACT, 2.0, 3.0}
|
|
};
|
|
|
|
fexcept_t _Flags = 0;
|
|
double _Ans = 0.0;
|
|
int _N;
|
|
|
|
if ((_Except &= FE_ALL_EXCEPT) == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* get the current status flags */
|
|
fegetexceptflag(&_Flags, FE_ALL_EXCEPT);
|
|
|
|
_Except &= ~_Flags;
|
|
_Flags |= _Except;
|
|
|
|
/* set the new status flags */
|
|
fesetexceptflag(&_Flags, FE_ALL_EXCEPT);
|
|
|
|
/* raise the exceptions not masked */
|
|
for (_N = 0; _N < sizeof(_Table) / sizeof(_Table[0]); ++_N)
|
|
{
|
|
if ((_Except & _Table[_N]._Except_Val) != 0)
|
|
{
|
|
_Ans = _Table[_N]._Num / _Table[_N]._Denom;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
__inline int __CRTDECL feupdateenv(_In_ const fenv_t *_Penv)
|
|
{
|
|
int _Except = fetestexcept(FE_ALL_EXCEPT);
|
|
|
|
if (fesetenv(_Penv) != 0 || feraiseexcept(_Except) != 0)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* !defined(_M_CEE) && !defined(_CRTBLD) */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
|
|
#pragma pack(pop)
|
|
|
|
#endif /* _FENV */
|