msvcrt: Move the fenv_t definition to the public header.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1f11f41f61
commit
34422eb56c
@ -146,12 +146,6 @@ struct MSVCRT_lconv
|
||||
wchar_t* _W_negative_sign;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int control;
|
||||
unsigned int status;
|
||||
} fenv_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double r;
|
||||
@ -798,13 +792,13 @@ static void test_feenv(void)
|
||||
ret = p_fegetenv(&env);
|
||||
ok(!ret, "fegetenv returned %x\n", ret);
|
||||
p_fesetround(FE_UPWARD);
|
||||
ok(env.control == (_EM_INEXACT|_EM_UNDERFLOW|_EM_OVERFLOW|_EM_ZERODIVIDE|_EM_INVALID),
|
||||
"env.control = %x\n", env.control);
|
||||
ok(!env.status, "env.status = %x\n", env.status);
|
||||
ok(env._Fe_ctl == (_EM_INEXACT|_EM_UNDERFLOW|_EM_OVERFLOW|_EM_ZERODIVIDE|_EM_INVALID),
|
||||
"env._Fe_ctl = %lx\n", env._Fe_ctl);
|
||||
ok(!env._Fe_stat, "env._Fe_stat = %lx\n", env._Fe_stat);
|
||||
ret = p_fegetenv(&env2);
|
||||
ok(!ret, "fegetenv returned %x\n", ret);
|
||||
ok(env2.control == (_EM_INEXACT|_EM_UNDERFLOW|_EM_OVERFLOW|_EM_ZERODIVIDE|_EM_INVALID | FE_UPWARD),
|
||||
"env2.control = %x\n", env2.control);
|
||||
ok(env2._Fe_ctl == (_EM_INEXACT|_EM_UNDERFLOW|_EM_OVERFLOW|_EM_ZERODIVIDE|_EM_INVALID | FE_UPWARD),
|
||||
"env2._Fe_ctl = %lx\n", env2._Fe_ctl);
|
||||
ret = p_fesetenv(&env);
|
||||
ok(!ret, "fesetenv returned %x\n", ret);
|
||||
ret = p_fegetround();
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fenv.h>
|
||||
#include <fpieee.h>
|
||||
#include <math.h>
|
||||
|
||||
@ -2065,11 +2066,11 @@ int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask
|
||||
/*********************************************************************
|
||||
* fegetenv (MSVCR120.@)
|
||||
*/
|
||||
int CDECL MSVCRT_fegetenv(MSVCRT_fenv_t *env)
|
||||
int CDECL MSVCRT_fegetenv(fenv_t *env)
|
||||
{
|
||||
env->control = _controlfp(0, 0) & (MSVCRT__EM_INEXACT | MSVCRT__EM_UNDERFLOW |
|
||||
env->_Fe_ctl = _controlfp(0, 0) & (MSVCRT__EM_INEXACT | MSVCRT__EM_UNDERFLOW |
|
||||
MSVCRT__EM_OVERFLOW | MSVCRT__EM_ZERODIVIDE | MSVCRT__EM_INVALID | MSVCRT__RC_CHOP);
|
||||
env->status = _statusfp();
|
||||
env->_Fe_stat = _statusfp();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@ -2160,7 +2161,7 @@ void CDECL _fpreset(void)
|
||||
/*********************************************************************
|
||||
* fesetenv (MSVCR120.@)
|
||||
*/
|
||||
int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env)
|
||||
int CDECL MSVCRT_fesetenv(const fenv_t *env)
|
||||
{
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
struct {
|
||||
@ -2180,7 +2181,7 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env)
|
||||
|
||||
TRACE( "(%p)\n", env );
|
||||
|
||||
if (!env->control && !env->status) {
|
||||
if (!env->_Fe_ctl && !env->_Fe_stat) {
|
||||
_fpreset();
|
||||
return 0;
|
||||
}
|
||||
@ -2188,12 +2189,12 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env)
|
||||
__asm__ __volatile__( "fnstenv %0" : "=m" (fenv) );
|
||||
|
||||
fenv.control_word &= ~0xc3d;
|
||||
if (env->control & MSVCRT__EM_INVALID) fenv.control_word |= 0x1;
|
||||
if (env->control & MSVCRT__EM_ZERODIVIDE) fenv.control_word |= 0x4;
|
||||
if (env->control & MSVCRT__EM_OVERFLOW) fenv.control_word |= 0x8;
|
||||
if (env->control & MSVCRT__EM_UNDERFLOW) fenv.control_word |= 0x10;
|
||||
if (env->control & MSVCRT__EM_INEXACT) fenv.control_word |= 0x20;
|
||||
switch (env->control & MSVCRT__MCW_RC)
|
||||
if (env->_Fe_ctl & MSVCRT__EM_INVALID) fenv.control_word |= 0x1;
|
||||
if (env->_Fe_ctl & MSVCRT__EM_ZERODIVIDE) fenv.control_word |= 0x4;
|
||||
if (env->_Fe_ctl & MSVCRT__EM_OVERFLOW) fenv.control_word |= 0x8;
|
||||
if (env->_Fe_ctl & MSVCRT__EM_UNDERFLOW) fenv.control_word |= 0x10;
|
||||
if (env->_Fe_ctl & MSVCRT__EM_INEXACT) fenv.control_word |= 0x20;
|
||||
switch (env->_Fe_ctl & MSVCRT__MCW_RC)
|
||||
{
|
||||
case MSVCRT__RC_UP|MSVCRT__RC_DOWN: fenv.control_word |= 0xc00; break;
|
||||
case MSVCRT__RC_UP: fenv.control_word |= 0x800; break;
|
||||
@ -2201,11 +2202,11 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env)
|
||||
}
|
||||
|
||||
fenv.status_word &= ~0x3d;
|
||||
if (env->status & MSVCRT__SW_INVALID) fenv.status_word |= 0x1;
|
||||
if (env->status & MSVCRT__SW_ZERODIVIDE) fenv.status_word |= 0x4;
|
||||
if (env->status & MSVCRT__SW_OVERFLOW) fenv.status_word |= 0x8;
|
||||
if (env->status & MSVCRT__SW_UNDERFLOW) fenv.status_word |= 0x10;
|
||||
if (env->status & MSVCRT__SW_INEXACT) fenv.status_word |= 0x20;
|
||||
if (env->_Fe_stat & FE_INVALID) fenv.status_word |= 0x1;
|
||||
if (env->_Fe_stat & FE_DIVBYZERO) fenv.status_word |= 0x4;
|
||||
if (env->_Fe_stat & FE_OVERFLOW) fenv.status_word |= 0x8;
|
||||
if (env->_Fe_stat & FE_UNDERFLOW) fenv.status_word |= 0x10;
|
||||
if (env->_Fe_stat & FE_INEXACT) fenv.status_word |= 0x20;
|
||||
|
||||
__asm__ __volatile__( "fldenv %0" : : "m" (fenv) : "st", "st(1)",
|
||||
"st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)" );
|
||||
@ -2215,12 +2216,12 @@ int CDECL MSVCRT_fesetenv(const MSVCRT_fenv_t *env)
|
||||
DWORD fpword;
|
||||
__asm__ __volatile__( "stmxcsr %0" : "=m" (fpword) );
|
||||
fpword &= ~0x7e80;
|
||||
if (env->control & MSVCRT__EM_INVALID) fpword |= 0x80;
|
||||
if (env->control & MSVCRT__EM_ZERODIVIDE) fpword |= 0x200;
|
||||
if (env->control & MSVCRT__EM_OVERFLOW) fpword |= 0x400;
|
||||
if (env->control & MSVCRT__EM_UNDERFLOW) fpword |= 0x800;
|
||||
if (env->control & MSVCRT__EM_INEXACT) fpword |= 0x1000;
|
||||
switch (env->control & MSVCRT__MCW_RC)
|
||||
if (env->_Fe_ctl & MSVCRT__EM_INVALID) fpword |= 0x80;
|
||||
if (env->_Fe_ctl & MSVCRT__EM_ZERODIVIDE) fpword |= 0x200;
|
||||
if (env->_Fe_ctl & MSVCRT__EM_OVERFLOW) fpword |= 0x400;
|
||||
if (env->_Fe_ctl & MSVCRT__EM_UNDERFLOW) fpword |= 0x800;
|
||||
if (env->_Fe_ctl & MSVCRT__EM_INEXACT) fpword |= 0x1000;
|
||||
switch (env->_Fe_ctl & MSVCRT__MCW_RC)
|
||||
{
|
||||
case MSVCRT__RC_CHOP: fpword |= 0x6000; break;
|
||||
case MSVCRT__RC_UP: fpword |= 0x4000; break;
|
||||
@ -3833,11 +3834,11 @@ double CDECL MSVCR120_acosh(double x)
|
||||
{
|
||||
if (x < 1)
|
||||
{
|
||||
MSVCRT_fenv_t env;
|
||||
fenv_t env;
|
||||
|
||||
*MSVCRT__errno() = MSVCRT_EDOM;
|
||||
MSVCRT_fegetenv(&env);
|
||||
env.status |= MSVCRT__SW_INVALID;
|
||||
env._Fe_stat |= FE_INVALID;
|
||||
MSVCRT_fesetenv(&env);
|
||||
return NAN;
|
||||
}
|
||||
@ -3851,11 +3852,11 @@ float CDECL MSVCR120_acoshf(float x)
|
||||
{
|
||||
if (x < 1)
|
||||
{
|
||||
MSVCRT_fenv_t env;
|
||||
fenv_t env;
|
||||
|
||||
*MSVCRT__errno() = MSVCRT_EDOM;
|
||||
MSVCRT_fegetenv(&env);
|
||||
env.status |= MSVCRT__SW_INVALID;
|
||||
env._Fe_stat |= FE_INVALID;
|
||||
MSVCRT_fesetenv(&env);
|
||||
return NAN;
|
||||
}
|
||||
@ -3878,13 +3879,13 @@ double CDECL MSVCR120_atanh(double x)
|
||||
double ret;
|
||||
|
||||
if (x > 1 || x < -1) {
|
||||
MSVCRT_fenv_t env;
|
||||
fenv_t env;
|
||||
|
||||
*MSVCRT__errno() = MSVCRT_EDOM;
|
||||
|
||||
/* on Linux atanh returns -NAN in this case */
|
||||
MSVCRT_fegetenv(&env);
|
||||
env.status |= MSVCRT__SW_INVALID;
|
||||
env._Fe_stat |= FE_INVALID;
|
||||
MSVCRT_fesetenv(&env);
|
||||
return NAN;
|
||||
}
|
||||
@ -3902,12 +3903,12 @@ float CDECL MSVCR120_atanhf(float x)
|
||||
float ret;
|
||||
|
||||
if (x > 1 || x < -1) {
|
||||
MSVCRT_fenv_t env;
|
||||
fenv_t env;
|
||||
|
||||
*MSVCRT__errno() = MSVCRT_EDOM;
|
||||
|
||||
MSVCRT_fegetenv(&env);
|
||||
env.status |= MSVCRT__SW_INVALID;
|
||||
env._Fe_stat |= FE_INVALID;
|
||||
MSVCRT_fesetenv(&env);
|
||||
return NAN;
|
||||
}
|
||||
@ -4084,7 +4085,7 @@ double CDECL _except1(DWORD fpe, _FP_OPERATION_CODE op, double arg, double res,
|
||||
{
|
||||
ULONG_PTR exception_arg;
|
||||
DWORD exception = 0;
|
||||
MSVCRT_fenv_t env;
|
||||
fenv_t env;
|
||||
DWORD fpword = 0;
|
||||
WORD operation;
|
||||
|
||||
@ -4101,43 +4102,43 @@ double CDECL _except1(DWORD fpe, _FP_OPERATION_CODE op, double arg, double res,
|
||||
if (fpe & 0x1) { /* overflow */
|
||||
if ((fpe == 0x1 && (cw & 0x8)) || (fpe==0x11 && (cw & 0x28))) {
|
||||
/* 32-bit version also sets SW_INEXACT here */
|
||||
env.status |= MSVCRT__SW_OVERFLOW;
|
||||
if (fpe & 0x10) env.status |= MSVCRT__SW_INEXACT;
|
||||
env._Fe_stat |= FE_OVERFLOW;
|
||||
if (fpe & 0x10) env._Fe_stat |= FE_INEXACT;
|
||||
res = signbit(res) ? -INFINITY : INFINITY;
|
||||
} else {
|
||||
exception = EXCEPTION_FLT_OVERFLOW;
|
||||
}
|
||||
} else if (fpe & 0x2) { /* underflow */
|
||||
if ((fpe == 0x2 && (cw & 0x10)) || (fpe==0x12 && (cw & 0x30))) {
|
||||
env.status |= MSVCRT__SW_UNDERFLOW;
|
||||
if (fpe & 0x10) env.status |= MSVCRT__SW_INEXACT;
|
||||
env._Fe_stat |= FE_UNDERFLOW;
|
||||
if (fpe & 0x10) env._Fe_stat |= FE_INEXACT;
|
||||
res = signbit(res) ? -0.0 : 0.0;
|
||||
} else {
|
||||
exception = EXCEPTION_FLT_UNDERFLOW;
|
||||
}
|
||||
} else if (fpe & 0x4) { /* zerodivide */
|
||||
if ((fpe == 0x4 && (cw & 0x4)) || (fpe==0x14 && (cw & 0x24))) {
|
||||
env.status |= MSVCRT__SW_ZERODIVIDE;
|
||||
if (fpe & 0x10) env.status |= MSVCRT__SW_INEXACT;
|
||||
env._Fe_stat |= FE_DIVBYZERO;
|
||||
if (fpe & 0x10) env._Fe_stat |= FE_INEXACT;
|
||||
} else {
|
||||
exception = EXCEPTION_FLT_DIVIDE_BY_ZERO;
|
||||
}
|
||||
} else if (fpe & 0x8) { /* invalid */
|
||||
if (fpe == 0x8 && (cw & 0x1)) {
|
||||
env.status |= MSVCRT__SW_INVALID;
|
||||
env._Fe_stat |= FE_INVALID;
|
||||
} else {
|
||||
exception = EXCEPTION_FLT_INVALID_OPERATION;
|
||||
}
|
||||
} else if (fpe & 0x10) { /* inexact */
|
||||
if (fpe == 0x10 && (cw & 0x20)) {
|
||||
env.status |= MSVCRT__SW_INEXACT;
|
||||
env._Fe_stat |= FE_INEXACT;
|
||||
} else {
|
||||
exception = EXCEPTION_FLT_INEXACT_RESULT;
|
||||
}
|
||||
}
|
||||
|
||||
if (exception)
|
||||
env.status = 0;
|
||||
env._Fe_stat = 0;
|
||||
MSVCRT_fesetenv(&env);
|
||||
if (exception)
|
||||
RaiseException(exception, 0, 1, &exception_arg);
|
||||
|
@ -985,12 +985,6 @@ struct MSVCRT__stat64 {
|
||||
#define MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS 0x03000000
|
||||
#define MSVCRT__EM_AMBIGUOUS 0x80000000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int control;
|
||||
unsigned int status;
|
||||
} MSVCRT_fenv_t;
|
||||
|
||||
#define MSVCRT_CLOCKS_PER_SEC 1000
|
||||
|
||||
/* signals */
|
||||
|
@ -13,10 +13,26 @@
|
||||
#define FE_DOWNWARD _RC_DOWN
|
||||
#define FE_TOWARDZERO _RC_CHOP
|
||||
|
||||
#define FE_INEXACT _SW_INEXACT
|
||||
#define FE_UNDERFLOW _SW_UNDERFLOW
|
||||
#define FE_OVERFLOW _SW_OVERFLOW
|
||||
#define FE_DIVBYZERO _SW_ZERODIVIDE
|
||||
#define FE_INVALID _SW_INVALID
|
||||
#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__msvcrt_ulong _Fe_ctl;
|
||||
__msvcrt_ulong _Fe_stat;
|
||||
} fenv_t;
|
||||
|
||||
_ACRTIMP int __cdecl fegetenv(fenv_t*);
|
||||
_ACRTIMP int __cdecl fesetenv(const fenv_t*);
|
||||
_ACRTIMP int __cdecl fegetround(void);
|
||||
_ACRTIMP int __cdecl fesetround(int);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Loading…
x
Reference in New Issue
Block a user