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 )