00001 #ifndef FLOATING_POINT_EXCEPTIONS_H
00002 #define FLOATING_POINT_EXCEPTIONS_H
00003
00004 #ifdef __GNUC__
00005 #include <fenv.h>
00006 #ifdef __SSE2__
00007 #include <xmmintrin.h>
00008 #endif
00009 #endif
00010
00011
00012 namespace boost_adaptbx { namespace floating_point {
00013
00034 void trap_exceptions(bool division_by_zero, bool invalid, bool overflow) {
00035 #ifdef __linux
00036 int enabled = 0;
00037 int disabled = 0;
00038 #ifdef FE_DIVBYZERO
00039 if (division_by_zero) enabled |= FE_DIVBYZERO;
00040 else disabled |= FE_DIVBYZERO;
00041 #endif
00042 #ifdef FE_INVALID
00043 if (invalid) enabled |= FE_INVALID;
00044 else disabled |= FE_INVALID;
00045 #endif
00046 #ifdef FE_OVERFLOW
00047 if(overflow) enabled |= FE_OVERFLOW;
00048 else disabled |= FE_OVERFLOW;
00049 #endif
00050 fedisableexcept(disabled);
00051 feenableexcept(enabled);
00052 #elif defined(__APPLE_CC__) && defined(__SSE2__)
00053 unsigned int mask
00054 = _MM_MASK_INEXACT | _MM_MASK_UNDERFLOW | _MM_MASK_DENORM;
00055 if (!division_by_zero) mask |= _MM_MASK_DIV_ZERO;
00056 if (!invalid) mask |= _MM_MASK_INVALID;
00057 if (!overflow) mask |= _MM_MASK_OVERFLOW;
00058 _MM_SET_EXCEPTION_MASK(mask);
00059 #endif
00060 }
00061
00062 bool is_division_by_zero_trapped() {
00063 #ifdef __linux
00064 #ifdef FE_DIVBYZERO
00065 return fegetexcept() & FE_DIVBYZERO;
00066 #else
00067 return false;
00068 #endif
00069 #elif defined(__APPLE_CC__) && defined(__SSE2__)
00070 return !(_MM_GET_EXCEPTION_MASK() & _MM_MASK_DIV_ZERO);
00071 #else
00072 return false;
00073 #endif
00074 }
00075
00076 bool is_invalid_trapped() {
00077 #ifdef __linux
00078 #ifdef FE_INVALID
00079 return fegetexcept() & FE_INVALID;
00080 #else
00081 return false;
00082 #endif
00083 #elif defined(__APPLE_CC__) && defined(__SSE2__)
00084 return !(_MM_GET_EXCEPTION_MASK() & _MM_MASK_INVALID);
00085 #else
00086 return false;
00087 #endif
00088 }
00089
00090 bool is_overflow_trapped() {
00091 #ifdef __linux
00092 #ifdef FE_OVERFLOW
00093 return fegetexcept() & FE_OVERFLOW;
00094 #else
00095 return false;
00096 #endif
00097 #elif defined(__APPLE_CC__) && defined(__SSE2__)
00098 return !(_MM_GET_EXCEPTION_MASK() & _MM_MASK_OVERFLOW);
00099 #else
00100 return false;
00101 #endif
00102 }
00103
00104 class exception_trapping
00105 {
00106 private:
00107 bool division_by_zero_on_entry, invalid_on_entry, overflow_on_entry;
00108 bool division_by_zero_, invalid_, overflow_;
00109
00110 public:
00111 enum { dont_trap=0, division_by_zero=1, invalid=2, overflow=4 };
00112
00113 exception_trapping(int flag)
00114 : division_by_zero_on_entry(is_division_by_zero_trapped()),
00115 invalid_on_entry(is_invalid_trapped()),
00116 overflow_on_entry(is_overflow_trapped()),
00117 division_by_zero_(flag & division_by_zero),
00118 invalid_(flag & invalid),
00119 overflow_(flag & overflow)
00120 {
00121 trap_exceptions(division_by_zero_, invalid_, overflow_);
00122 }
00123
00124 ~exception_trapping() {
00125 trap_exceptions(division_by_zero_on_entry,
00126 invalid_on_entry,
00127 overflow_on_entry);
00128 }
00129 };
00130
00131 }}
00132
00133 #endif // GUARD