00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifndef G4FPEDetection_h
00041 #define G4FPEDetection_h 1
00042
00043 #include <iostream>
00044 #include <stdlib.h>
00045
00046 #ifdef __linux__
00047 #ifdef __GNUC__
00048 #include <features.h>
00049 #include <fenv.h>
00050 #include <csignal>
00051
00052 struct sigaction termaction, oldaction;
00053
00054 static void TerminationSignalHandler(int sig, siginfo_t* sinfo, void* )
00055 {
00056 std::cerr << "ERROR: " << sig;
00057 std::string message = "Floating-point exception (FPE).";
00058
00059 if (sinfo) {
00060 switch (sinfo->si_code) {
00061 #ifdef FPE_NOOP
00062 case FPE_NOOP:
00063 #endif
00064 case FPE_INTDIV:
00065 message = "Integer divide by zero.";
00066 break;
00067 case FPE_INTOVF:
00068 message = "Integer overflow.";
00069 break;
00070 case FPE_FLTDIV:
00071 message = "Floating point divide by zero.";
00072 break;
00073 case FPE_FLTOVF:
00074 message = "Floating point overflow.";
00075 break;
00076 case FPE_FLTUND:
00077 message = "Floating point underflow.";
00078 break;
00079 case FPE_FLTRES:
00080 message = "Floating point inexact result.";
00081 break;
00082 case FPE_FLTINV:
00083 message = "Floating point invalid operation.";
00084 break;
00085 case FPE_FLTSUB:
00086 message = "Subscript out of range.";
00087 break;
00088 default:
00089 message = "Unknown error.";
00090 break;
00091 }
00092 }
00093
00094 std::cerr << " - " << message << std::endl;
00095
00096 ::abort();
00097 }
00098
00099 static void InvalidOperationDetection()
00100 {
00101 std::cout << std::endl
00102 << " "
00103 << "############################################" << std::endl
00104 << " "
00105 << "!!! WARNING - FPE detection is activated !!!" << std::endl
00106 << " "
00107 << "############################################" << std::endl;
00108
00109 (void) feenableexcept( FE_DIVBYZERO );
00110 (void) feenableexcept( FE_INVALID );
00111
00112
00113
00114 sigdelset(&termaction.sa_mask,SIGFPE);
00115 termaction.sa_sigaction=TerminationSignalHandler;
00116 termaction.sa_flags=SA_SIGINFO;
00117 sigaction(SIGFPE, &termaction, &oldaction);
00118 }
00119 #endif
00120 #elif __MACH__
00121
00122 #include <fenv.h>
00123 #include <signal.h>
00124
00125 #define DEFINED_PPC (defined(__ppc__) || defined(__ppc64__))
00126 #define DEFINED_INTEL (defined(__i386__) || defined(__x86_64__))
00127
00128 #if DEFINED_PPC
00129
00130 #define FE_EXCEPT_SHIFT 22 // shift flags right to get masks
00131 #define FM_ALL_EXCEPT FE_ALL_EXCEPT >> FE_EXCEPT_SHIFT
00132
00133 static inline int feenableexcept (unsigned int excepts)
00134 {
00135 static fenv_t fenv;
00136 unsigned int new_excepts = (excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT,
00137 old_excepts;
00138
00139 if ( fegetenv (&fenv) ) { return -1; }
00140 old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
00141 fenv = (fenv & ~new_excepts) | new_excepts;
00142
00143 return ( fesetenv (&fenv) ? -1 : old_excepts );
00144 }
00145
00146 static inline int fedisableexcept (unsigned int excepts)
00147 {
00148 static fenv_t fenv;
00149 unsigned int still_on = ~((excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT),
00150 old_excepts;
00151
00152 if ( fegetenv (&fenv) ) { return -1; }
00153 old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
00154 fenv &= still_on;
00155
00156 return ( fesetenv (&fenv) ? -1 : old_excepts );
00157 }
00158
00159 #elif DEFINED_INTEL
00160
00161 static inline int feenableexcept (unsigned int excepts)
00162 {
00163 static fenv_t fenv;
00164 unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
00165 old_excepts;
00166
00167 if ( fegetenv (&fenv) ) { return -1; }
00168 old_excepts = fenv.__control & FE_ALL_EXCEPT;
00169
00170
00171
00172 fenv.__control &= ~new_excepts;
00173 fenv.__mxcsr &= ~(new_excepts << 7);
00174
00175 return ( fesetenv (&fenv) ? -1 : old_excepts );
00176 }
00177
00178 static inline int fedisableexcept (unsigned int excepts)
00179 {
00180 static fenv_t fenv;
00181 unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
00182 old_excepts;
00183
00184 if ( fegetenv (&fenv) ) { return -1; }
00185 old_excepts = fenv.__control & FE_ALL_EXCEPT;
00186
00187
00188
00189 fenv.__control |= new_excepts;
00190 fenv.__mxcsr |= new_excepts << 7;
00191
00192 return ( fesetenv (&fenv) ? -1 : old_excepts );
00193 }
00194
00195 #endif
00196
00197 static void TerminationSignalHandler(int sig, siginfo_t* sinfo, void* )
00198 {
00199 std::cerr << "ERROR: " << sig;
00200 std::string message = "Floating-point exception (FPE).";
00201
00202 if (sinfo) {
00203 switch (sinfo->si_code) {
00204 #ifdef FPE_NOOP
00205 case FPE_NOOP:
00206 #endif
00207 case FPE_INTDIV:
00208 message = "Integer divide by zero.";
00209 break;
00210 case FPE_INTOVF:
00211 message = "Integer overflow.";
00212 break;
00213 case FPE_FLTDIV:
00214 message = "Floating point divide by zero.";
00215 break;
00216 case FPE_FLTOVF:
00217 message = "Floating point overflow.";
00218 break;
00219 case FPE_FLTUND:
00220 message = "Floating point underflow.";
00221 break;
00222 case FPE_FLTRES:
00223 message = "Floating point inexact result.";
00224 break;
00225 case FPE_FLTINV:
00226 message = "Floating point invalid operation.";
00227 break;
00228 case FPE_FLTSUB:
00229 message = "Subscript out of range.";
00230 break;
00231 default:
00232 message = "Unknown error.";
00233 break;
00234 }
00235 }
00236
00237 std::cerr << " - " << message << std::endl;
00238
00239 ::abort();
00240 }
00241
00242 static void InvalidOperationDetection()
00243 {
00244 struct sigaction termaction, oldaction;
00245
00246 std::cout << std::endl
00247 << " "
00248 << "############################################" << std::endl
00249 << " "
00250 << "!!! WARNING - FPE detection is activated !!!" << std::endl
00251 << " "
00252 << "############################################" << std::endl;
00253
00254 feenableexcept ( FE_DIVBYZERO );
00255 feenableexcept ( FE_INVALID );
00256
00257
00258
00259 sigdelset(&termaction.sa_mask,SIGFPE);
00260 termaction.sa_sigaction=TerminationSignalHandler;
00261 termaction.sa_flags=SA_SIGINFO;
00262 sigaction(SIGFPE, &termaction, &oldaction);
00263 }
00264 #else
00265
00266 static void InvalidOperationDetection() {;}
00267
00268 #endif
00269
00270 #endif