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