00001 // 00002 // $Id: FloatingPoint.cpp,v 1.2 2008/07/14 23:33:53 lxmota Exp $ 00003 // 00004 // $Log: FloatingPoint.cpp,v $ 00005 // Revision 1.2 2008/07/14 23:33:53 lxmota 00006 // Updated to work on MacOS X (Darwin) 00007 // 00008 // Revision 1.1 2008/07/14 17:50:46 lxmota 00009 // Initial sources. 00010 // 00011 // 00012 00013 // 00014 // 2001/10/02 22:45:15 by Jaroslaw Knap 00015 // Imported sources. 00016 // 00017 00018 #include <fenv.h> 00019 00020 #include "FloatingPoint.h" 00021 00022 bool LCM::FloatingPoint::active_ = false; 00023 unsigned LCM::FloatingPoint::oldMask_ = LCM::emptyMask_; 00024 00025 // 00026 // 00027 // 00028 00029 namespace LCM { 00030 00031 FloatingPoint::FloatingPoint() 00032 { 00033 00034 if (active_) return; 00035 00036 oldMask_ = getCurrentMask(); 00037 active_ = true; 00038 return; 00039 00040 } 00041 00042 FloatingPoint::~FloatingPoint() 00043 { 00044 00045 if (!active_) return; 00046 00047 setMask(oldMask_); 00048 active_ = false; 00049 return; 00050 00051 } 00052 00053 00054 } 00055 00056 00057 // 00058 // all architectures with <fenv.h> available 00059 // 00060 00061 // 00062 // fully ISO/IEC C99 compliant 00063 // 00064 00065 #if defined(HAVE_FESETTRAPENABLE) 00066 00067 // set traps 00068 00069 namespace LCM { 00070 00071 void FloatingPoint::trapInexact() 00072 { 00073 00074 fesettrapenable(FE_INEXACT); 00075 return; 00076 00077 } 00078 00079 void FloatingPoint::trapDivbyzero() 00080 { 00081 00082 fesettrapenable(FE_DIVBYZERO); 00083 return; 00084 00085 } 00086 00087 void FloatingPoint::trapUnderflow() 00088 { 00089 00090 fesettrapenable(FE_UNDERFLOW); 00091 return; 00092 00093 } 00094 00095 void FloatingPoint::trapOverflow() 00096 { 00097 00098 fesettrapenable(FE_OVERFLOW); 00099 return; 00100 00101 } 00102 00103 void FloatingPoint::trapInvalid() 00104 { 00105 00106 fesettrapenable(FE_INVALID); 00107 return; 00108 00109 } 00110 00111 // get current trap mask 00112 00113 unsigned FloatingPoint::getCurrentMask() 00114 { 00115 00116 unsigned currentMask = emptyMask_; 00117 int currentTraps = fegettrapenable(); 00118 00119 if (currentTraps & FE_INEXACT) currentMask |= inexactMask_; 00120 if (currentTraps & FE_DIVBYZERO) currentMask |= divbyzeroMask_; 00121 if (currentTraps & FE_UNDERFLOW) currentMask |= underflowMask_; 00122 if (currentTraps & FE_OVERFLOW) currentMask |= overflowMask_; 00123 if (currentTraps & FE_INVALID) currentMask |= invalidMask_; 00124 00125 return currentMask; 00126 00127 } 00128 00129 // set mask 00130 00131 void FloatingPoint::setMask(unsigned mask) 00132 { 00133 00134 int currentTraps = 0; 00135 00136 if (mask & inexactMask_) currentTraps |= FE_INEXACT; 00137 if (mask & divbyzeroMask_) currentTraps |= FE_DIVBYZERO; 00138 if (mask & underflowMask_) currentTraps |= FE_UNDERFLOW; 00139 if (mask & overflowMask_) currentTraps |= FE_OVERFLOW; 00140 if (mask & invalidMask_) currentTraps |= FE_INVALID; 00141 00142 fesettrapenable(currentTraps); 00143 00144 return; 00145 00146 } 00147 00148 } 00149 00150 #else 00151 00152 #if defined(__linux__) 00153 00154 // 00155 // subset of ISO/IEC C99; (linux) 00156 // 00157 00158 void LCM::FloatingPoint::trapInexact() 00159 { 00160 feenableexcept( fegetexcept() | FE_INEXACT ); 00161 return; 00162 } 00163 00164 void LCM::FloatingPoint::trapDivbyzero() 00165 { 00166 feenableexcept( fegetexcept() | FE_DIVBYZERO ); 00167 return; 00168 } 00169 00170 void LCM::FloatingPoint::trapUnderflow() 00171 { 00172 feenableexcept( fegetexcept() | FE_UNDERFLOW ); 00173 return; 00174 } 00175 00176 void LCM::FloatingPoint::trapOverflow() 00177 { 00178 feenableexcept( fegetexcept() | FE_OVERFLOW ); 00179 return; 00180 } 00181 00182 void LCM::FloatingPoint::trapInvalid() 00183 { 00184 feenableexcept( fegetexcept() | FE_INVALID ); 00185 return; 00186 } 00187 00188 unsigned LCM::FloatingPoint::getCurrentMask() 00189 { 00190 return fegetexcept(); 00191 } 00192 00193 // set mask 00194 00195 void LCM::FloatingPoint::setMask(unsigned mask) 00196 { 00197 feenableexcept( mask ); 00198 return; 00199 } 00200 00201 #else 00202 00203 // 00204 // dummy interfaces 00205 // 00206 00207 void LCM::FloatingPoint::trapInexact() 00208 { 00209 00210 return; 00211 00212 } 00213 00214 void LCM::FloatingPoint::trapDivbyzero() 00215 { 00216 00217 return; 00218 00219 } 00220 00221 void LCM::FloatingPoint::trapUnderflow() 00222 { 00223 00224 return; 00225 00226 } 00227 00228 void LCM::FloatingPoint::trapOverflow() 00229 { 00230 00231 return; 00232 00233 } 00234 00235 void LCM::FloatingPoint::trapInvalid() 00236 { 00237 00238 return; 00239 00240 } 00241 00242 unsigned LCM::FloatingPoint::getCurrentMask() 00243 { 00244 00245 return emptyMask_; 00246 00247 } 00248 00249 // set mask 00250 00251 void LCM::FloatingPoint::setMask(unsigned mask) 00252 { 00253 00254 return; 00255 00256 } 00257 00258 #endif // linux 00259 00260 #endif // HAVE_FESETTRAPENABLE