Math-Geometry-Delaunay
view release on metacpan or search on metacpan
src/xpfpa.h view on Meta::CPAN
{ \
float _xpfpa_result = (val); \
XPFPA_RESTORE() \
return _xpfpa_result; \
}
// This won't work, but we add a macro for it anyway.
# define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
{ \
long double _xpfpa_result = (val); \
XPFPA_RESTORE() \
return _xpfpa_result; \
}
#elif defined(HAVE__CONTROLFP)
// float.h defines _controlfp
# include <float.h>
# define XPFPA_DECLARE() \
unsigned int _xpfpa_fpu_oldcw;
# define XPFPA_SWITCH_DOUBLE() \
_xpfpa_fpu_oldcw = _controlfp(0, 0); \
_controlfp(_PC_53, _MCW_PC);
# define XPFPA_SWITCH_SINGLE() \
_xpfpa_fpu_oldcw = _controlfp(0, 0); \
_controlfp(_PC_24, _MCW_PC);
// NOTE: This will only work as expected on MinGW.
# define XPFPA_SWITCH_DOUBLE_EXTENDED() \
_xpfpa_fpu_oldcw = _controlfp(0, 0); \
_controlfp(_PC_64, _MCW_PC);
# define XPFPA_RESTORE() \
_controlfp(_xpfpa_fpu_oldcw, _MCW_PC);
// We do NOT use the volatile return trick since _controlfp is a function
// call and thus FP registers are saved in memory anyway. However, we do use
// a variable to ensure that the expression passed into val will be evaluated
// *before* switching back contexts.
# define XPFPA_RETURN_DOUBLE(val) \
{ \
double _xpfpa_result = (val); \
XPFPA_RESTORE() \
return _xpfpa_result; \
}
# define XPFPA_RETURN_SINGLE(val) \
{ \
float _xpfpa_result = (val); \
XPFPA_RESTORE() \
return _xpfpa_result; \
}
// This will only work on MinGW
# define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
{ \
long double _xpfpa_result = (val); \
XPFPA_RESTORE() \
return _xpfpa_result; \
}
#elif defined(HAVE__FESETENV) // C++11 fenv.h available
// fenv.h defines functions fegetenv and fesetenv and type fenv_t
# include <fenv.h>
#define _FPU_EXTENDED 0x300
#define _FPU_DOUBLE 0x200
#define _FPU_SINGLE 0x0
# define XPFPA_DECLARE() \
fenv_t _xpfpa_fpu;
unsigned short int _xpfpa_fpu_oldcw;
# define XPFPA_SWITCH_DOUBLE() \
fegetenv(&_xpfpa_fpu); \
_xpfpa_fpu_oldcw = _xpfpa_fpu.__control_word; \
_xpfpa_fpu.__control_word = (_xpfpa_fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_SINGLE) | _FPU_DOUBLE; \
fesetenv(&_xpfpa_fpu);
# define XPFPA_SWITCH_SINGLE() \
fegetenv(&_xpfpa_fpu); \
_xpfpa_fpu_oldcw = _xpfpa_fpu.__control_word; \
_xpfpa_fpu.__control_word = (_xpfpa_fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_DOUBLE) | _FPU_SINGLE; \
fesetenv(&_xpfpa_fpu);
# define XPFPA_SWITCH_DOUBLE_EXTENDED() \
fegetenv(&_xpfpa_fpu); \
_xpfpa_fpu_oldcw = _xpfpa_fpu.__control_word; \
_xpfpa_fpu.__control_word = (_xpfpa_fpu_oldcw & ~_FPU_SINGLE & ~_FPU_DOUBLE) | _FPU_EXTENDED; \
fesetenv(&_xpfpa_fpu);
# define XPFPA_RESTORE() \
fegetenv(&_xpfpa_fpu); \
_xpfpa_fpu.__control_word = _xpfpa_fpu_oldcw; \
fesetenv(&_xpfpa_fpu);
// We use a temporary volatile variable (in a new block) in order to ensure
// that the optimizer does not mis-optimize the instructions. Also, a volatile
// variable ensures truncation to correct precision.
# define XPFPA_RETURN_DOUBLE(val) \
{ \
volatile double _xpfpa_result = (val); \
XPFPA_RESTORE() \
return _xpfpa_result; \
}
# define XPFPA_RETURN_SINGLE(val) \
{ \
volatile float _xpfpa_result = (val); \
XPFPA_RESTORE() \
return _xpfpa_result; \
}
# define XPFPA_RETURN_DOUBLE_EXTENDED(val) \
{ \
volatile long double _xpfpa_result = (val); \
XPFPA_RESTORE() \
return _xpfpa_result; \
}
#elif defined(HAVE__FPU_SETCW) // older glibc fpu_control.h
// fpu_control.h defines _FPU_[GS]ETCW
# include <fpu_control.h>
# define XPFPA_DECLARE() \
fpu_control_t _xpfpa_fpu_oldcw, _xpfpa_fpu_cw;
# define XPFPA_SWITCH_DOUBLE() \
_FPU_GETCW(_xpfpa_fpu_oldcw); \
_xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_SINGLE) | _FPU_DOUBLE; \
_FPU_SETCW(_xpfpa_fpu_cw);
# define XPFPA_SWITCH_SINGLE() \
_FPU_GETCW(_xpfpa_fpu_oldcw); \
_xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~_FPU_EXTENDED & ~_FPU_DOUBLE) | _FPU_SINGLE; \
_FPU_SETCW(_xpfpa_fpu_cw);
# define XPFPA_SWITCH_DOUBLE_EXTENDED() \
_FPU_GETCW(_xpfpa_fpu_oldcw); \
_xpfpa_fpu_cw = (_xpfpa_fpu_oldcw & ~_FPU_SINGLE & ~_FPU_DOUBLE) | _FPU_EXTENDED; \
_FPU_SETCW(_xpfpa_fpu_cw);
# define XPFPA_RESTORE() \
_FPU_SETCW(_xpfpa_fpu_oldcw);
// We use a temporary volatile variable (in a new block) in order to ensure
// that the optimizer does not mis-optimize the instructions. Also, a volatile
// variable ensures truncation to correct precision.
# define XPFPA_RETURN_DOUBLE(val) \
{ \
volatile double _xpfpa_result = (val); \
XPFPA_RESTORE() \
return _xpfpa_result; \
}
# define XPFPA_RETURN_SINGLE(val) \
{ \
volatile float _xpfpa_result = (val); \
XPFPA_RESTORE() \
return _xpfpa_result; \
}
( run in 0.460 second using v1.01-cache-2.11-cpan-140bd7fdf52 )