38#ifndef G4FPEDetection_hh
39#define G4FPEDetection_hh 1
45# if(defined(__GNUC__) && !defined(__clang__))
53struct sigaction termaction, oldaction;
55static void G4StackBackTrace()
60 int nptrs = backtrace(buffer, BSIZE);
61 char** strings = backtrace_symbols(buffer, nptrs);
64 perror(
"backtrace_symbols");
67 std::cerr << std::endl <<
"Call Stack:" << std::endl;
68 for(
int j = 0; j < nptrs; j++)
70 std::cerr << nptrs - j - 1 <<
": ";
71 char* mangled_start = strchr(strings[j],
'(') + 1;
73 *(mangled_start - 1) =
'\0';
74 char* mangled_end = strchr(mangled_start,
'+');
79 if(mangled_end && strlen(mangled_start))
80 realname = abi::__cxa_demangle(mangled_start, 0, 0, &status);
83 std::cerr << strings[j] <<
" : " << realname << std::endl;
88 std::cerr << strings[j] << std::endl;
97static void TerminationSignalHandler(
int sig, siginfo_t* sinfo,
100 std::cerr <<
"ERROR: " << sig;
101 std::string message =
"Floating-point exception (FPE).";
105 switch(sinfo->si_code)
111 message =
"Integer divide by zero.";
114 message =
"Integer overflow.";
117 message =
"Floating point divide by zero.";
120 message =
"Floating point overflow.";
123 message =
"Floating point underflow.";
126 message =
"Floating point inexact result.";
129 message =
"Floating point invalid operation.";
132 message =
"Subscript out of range.";
135 message =
"Unknown error.";
139 std::cerr <<
" - " << message << std::endl;
144static void InvalidOperationDetection()
146 std::cout << std::endl
148 <<
"############################################" << std::endl
150 <<
"!!! WARNING - FPE detection is activated !!!" << std::endl
152 <<
"############################################" << std::endl;
154 (void) feenableexcept(FE_DIVBYZERO);
155 (void) feenableexcept(FE_INVALID);
159 sigfillset(&termaction.sa_mask);
160 sigdelset(&termaction.sa_mask, SIGFPE);
161 termaction.sa_sigaction = TerminationSignalHandler;
162 termaction.sa_flags = SA_SIGINFO;
163 sigaction(SIGFPE, &termaction, &oldaction);
168static void InvalidOperationDetection() { ; }
172#elif defined(__MACH__)
180# if(defined(__ppc__) || defined(__ppc64__))
182# define FE_EXCEPT_SHIFT 22
183# define FM_ALL_EXCEPT FE_ALL_EXCEPT >> FE_EXCEPT_SHIFT
185static inline int feenableexcept(
unsigned int excepts)
188 unsigned int new_excepts = (excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT,
195 old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
196 fenv = (fenv & ~new_excepts) | new_excepts;
198 return (fesetenv(&fenv) ? -1 : old_excepts);
201static inline int fedisableexcept(
unsigned int excepts)
204 unsigned int still_on = ~((excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT),
211 old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
214 return (fesetenv(&fenv) ? -1 : old_excepts);
217# elif(defined(__i386__) || defined(__x86_64__))
219static inline int feenableexcept(
unsigned int excepts)
222 unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
229 old_excepts = fenv.__control & FE_ALL_EXCEPT;
233 fenv.__control &= ~new_excepts;
234 fenv.__mxcsr &= ~(new_excepts << 7);
236 return (fesetenv(&fenv) ? -1 : old_excepts);
239static inline int fedisableexcept(
unsigned int excepts)
242 unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
249 old_excepts = fenv.__control & FE_ALL_EXCEPT;
253 fenv.__control |= new_excepts;
254 fenv.__mxcsr |= new_excepts << 7;
256 return (fesetenv(&fenv) ? -1 : old_excepts);
259# elif(defined(__arm) || defined(__arm64) || defined(__aarch64__))
261# define FE_EXCEPT_SHIFT 22
262# define FM_ALL_EXCEPT FE_ALL_EXCEPT >> FE_EXCEPT_SHIFT
264static inline int feenableexcept(
unsigned int excepts)
267 unsigned int new_excepts = (excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT,
274 old_excepts = (fenv.__fpcr & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
275 fenv.__fpcr = (fenv.__fpcr & ~new_excepts) | new_excepts;
277 return (fesetenv(&fenv) ? -1 : old_excepts);
280static inline int fedisableexcept(
unsigned int excepts)
283 unsigned int still_on = ~((excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT),
290 old_excepts = (fenv.__fpcr & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
291 fenv.__fpcr = fenv.__fpcr | still_on;
293 return (fesetenv(&fenv) ? -1 : old_excepts);
298static void TerminationSignalHandler(
int sig, siginfo_t* sinfo,
301 std::cerr <<
"ERROR: " << sig;
302 std::string message =
"Floating-point exception (FPE).";
306 switch(sinfo->si_code)
312 message =
"Integer divide by zero.";
315 message =
"Integer overflow.";
318 message =
"Floating point divide by zero.";
321 message =
"Floating point overflow.";
324 message =
"Floating point underflow.";
327 message =
"Floating point inexact result.";
330 message =
"Floating point invalid operation.";
333 message =
"Subscript out of range.";
336 message =
"Unknown error.";
341 std::cerr <<
" - " << message << std::endl;
346static void InvalidOperationDetection()
348 struct sigaction termaction, oldaction;
350 std::cout << std::endl
352 <<
"############################################" << std::endl
354 <<
"!!! WARNING - FPE detection is activated !!!" << std::endl
356 <<
"############################################" << std::endl;
358 feenableexcept(FE_DIVBYZERO);
359 feenableexcept(FE_INVALID);
363 sigfillset(&termaction.sa_mask);
364 sigdelset(&termaction.sa_mask, SIGFPE);
365 termaction.sa_sigaction = TerminationSignalHandler;
366 termaction.sa_flags = SA_SIGINFO;
367 sigaction(SIGFPE, &termaction, &oldaction);
372static void InvalidOperationDetection() { ; }