xref: /petsc/src/sys/error/fp.c (revision bd2b07b136135af06fb9210476dad9bf59a36938)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
30e3d61c9SBarry Smith    IEEE error handler for all machines. Since each OS has
40e3d61c9SBarry Smith    enough slight differences we have completely separate codes for each one.
5e5c89e4eSSatish Balay */
6b014e56cSJed Brown 
7b014e56cSJed Brown /*
8b014e56cSJed Brown   This feature test macro provides FE_NOMASK_ENV on GNU.  It must be defined
9b014e56cSJed Brown   at the top of the file because other headers may pull in fenv.h even when
10b014e56cSJed Brown   not strictly necessary.  Strictly speaking, we could include ONLY petscconf.h,
11b014e56cSJed Brown   check PETSC_HAVE_FENV_H, and only define _GNU_SOURCE in that case, but such
12b014e56cSJed Brown   shenanigans ought to be unnecessary.
13b014e56cSJed Brown */
14519f805aSKarl Rupp #if !defined(_GNU_SOURCE)
15b014e56cSJed Brown #define _GNU_SOURCE
1676a6984eSJed Brown #endif
17b014e56cSJed Brown 
1827104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I  "petscsys.h"  I*/
19e5c89e4eSSatish Balay #include <signal.h>
20e5c89e4eSSatish Balay 
21670f3ff9SJed Brown struct PetscFPTrapLink {
22670f3ff9SJed Brown   PetscFPTrap             trapmode;
23670f3ff9SJed Brown   struct PetscFPTrapLink *next;
24670f3ff9SJed Brown };
25aba4c478SBarry Smith static PetscFPTrap             _trapmode = PETSC_FP_TRAP_OFF; /* Current trapping mode; see PetscDetermineInitialFPTrap() */
26670f3ff9SJed Brown static struct PetscFPTrapLink *_trapstack;                    /* Any pushed states of _trapmode */
27670f3ff9SJed Brown 
28670f3ff9SJed Brown /*@
29cc9df77eSBarry Smith    PetscFPTrapPush - push a floating point trapping mode, restored using PetscFPTrapPop()
30670f3ff9SJed Brown 
31670f3ff9SJed Brown    Not Collective
32670f3ff9SJed Brown 
334165533cSJose E. Roman    Input Parameter:
34cf0818bdSBarry Smith .    trap - PETSC_FP_TRAP_ON or PETSC_FP_TRAP_OFF or any of the values passable to `PetscSetFPTrap()`
35670f3ff9SJed Brown 
36670f3ff9SJed Brown    Level: advanced
37670f3ff9SJed Brown 
38cc9df77eSBarry Smith    Notes:
39cc9df77eSBarry Smith      This only changes the trapping if the new mode is different than the current mode.
40cc9df77eSBarry Smith 
41cc9df77eSBarry Smith      This routine is called to turn off trapping for certain LAPACK routines that assume that dividing
42cc9df77eSBarry Smith      by zero is acceptable. In particular the routine ieeeck().
43cc9df77eSBarry Smith 
44cc9df77eSBarry Smith      Most systems by default have all trapping turned off, but certain Fortran compilers have
45cc9df77eSBarry Smith      link flags that turn on trapping before the program begins.
46cc9df77eSBarry Smith $       gfortran -ffpe-trap=invalid,zero,overflow,underflow,denormal
47cc9df77eSBarry Smith $       ifort -fpe0
48cc9df77eSBarry Smith 
49db781477SPatrick Sanan .seealso: `PetscFPTrapPop()`, `PetscSetFPTrap()`, `PetscDetermineInitialFPTrap()`
50670f3ff9SJed Brown @*/
519371c9d4SSatish Balay PetscErrorCode PetscFPTrapPush(PetscFPTrap trap) {
52670f3ff9SJed Brown   struct PetscFPTrapLink *link;
53670f3ff9SJed Brown 
54670f3ff9SJed Brown   PetscFunctionBegin;
559566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
561f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP)
571f006be4SPierre Jolivet #pragma omp critical
581f006be4SPierre Jolivet #endif
591f006be4SPierre Jolivet   {
60670f3ff9SJed Brown     link->trapmode = _trapmode;
61670f3ff9SJed Brown     link->next     = _trapstack;
62670f3ff9SJed Brown     _trapstack     = link;
631f006be4SPierre Jolivet   }
649566063dSJacob Faibussowitsch   if (trap != _trapmode) PetscCall(PetscSetFPTrap(trap));
65670f3ff9SJed Brown   PetscFunctionReturn(0);
66670f3ff9SJed Brown }
67670f3ff9SJed Brown 
68670f3ff9SJed Brown /*@
69670f3ff9SJed Brown    PetscFPTrapPop - push a floating point trapping mode, to be restored using PetscFPTrapPop()
70670f3ff9SJed Brown 
71670f3ff9SJed Brown    Not Collective
72670f3ff9SJed Brown 
73670f3ff9SJed Brown    Level: advanced
74670f3ff9SJed Brown 
75db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscSetFPTrap()`, `PetscDetermineInitialFPTrap()`
76670f3ff9SJed Brown @*/
779371c9d4SSatish Balay PetscErrorCode PetscFPTrapPop(void) {
78670f3ff9SJed Brown   struct PetscFPTrapLink *link;
79670f3ff9SJed Brown 
80670f3ff9SJed Brown   PetscFunctionBegin;
819566063dSJacob Faibussowitsch   if (_trapstack->trapmode != _trapmode) PetscCall(PetscSetFPTrap(_trapstack->trapmode));
821f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP)
831f006be4SPierre Jolivet #pragma omp critical
841f006be4SPierre Jolivet #endif
851f006be4SPierre Jolivet   {
86670f3ff9SJed Brown     link       = _trapstack;
87670f3ff9SJed Brown     _trapstack = _trapstack->next;
881f006be4SPierre Jolivet   }
899566063dSJacob Faibussowitsch   PetscCall(PetscFree(link));
90670f3ff9SJed Brown   PetscFunctionReturn(0);
91670f3ff9SJed Brown }
92670f3ff9SJed Brown 
93e5c89e4eSSatish Balay /*--------------------------------------- ---------------------------------------------------*/
94e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP)
95e5c89e4eSSatish Balay #include <floatingpoint.h>
96e5c89e4eSSatish Balay 
978cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_flags(char *, char *, char *, char **);
988cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_handler(char *, char *, sigfpe_handler_type(int, int, struct sigcontext *, char *));
99e5c89e4eSSatish Balay 
1009371c9d4SSatish Balay static struct {
1019371c9d4SSatish Balay   int   code_no;
1029371c9d4SSatish Balay   char *name;
1039371c9d4SSatish Balay } error_codes[] = {
104e5c89e4eSSatish Balay   {FPE_INTDIV_TRAP,   "integer divide"               },
105e5c89e4eSSatish Balay   {FPE_FLTOPERR_TRAP, "IEEE operand error"           },
106e5c89e4eSSatish Balay   {FPE_FLTOVF_TRAP,   "floating point overflow"      },
107e5c89e4eSSatish Balay   {FPE_FLTUND_TRAP,   "floating point underflow"     },
108e5c89e4eSSatish Balay   {FPE_FLTDIV_TRAP,   "floating pointing divide"     },
109e5c89e4eSSatish Balay   {FPE_FLTINEX_TRAP,  "inexact floating point result"},
110e5c89e4eSSatish Balay   {0,                 "unknown error"                }
111e5c89e4eSSatish Balay };
112e5c89e4eSSatish Balay #define SIGPC(scp) (scp->sc_pc)
113e5c89e4eSSatish Balay 
114cf0818bdSBarry Smith /* this function gets called if a trap has occurred and been caught */
1159371c9d4SSatish Balay sigfpe_handler_type PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp, char *addr) {
1165f80ce2aSJacob Faibussowitsch   int err_ind = -1;
117e5c89e4eSSatish Balay 
118e5c89e4eSSatish Balay   PetscFunctionBegin;
1195f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
120e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
121e5c89e4eSSatish Balay   }
122e5c89e4eSSatish Balay 
123a297a907SKarl Rupp   if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp));
124a297a907SKarl Rupp   else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp));
125a297a907SKarl Rupp 
12649c86fc7SBarry Smith   (void)PetscError(PETSC_COMM_SELF, PETSC_ERR_FP, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
12741e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
128e5c89e4eSSatish Balay   PetscFunctionReturn(0);
129e5c89e4eSSatish Balay }
130e5c89e4eSSatish Balay 
131e30d2299SSatish Balay /*@
132cf0818bdSBarry Smith    PetscSetFPTrap - Enables traps/exceptions on common floating point errors. This option may not work on certain systems or only a
133cf0818bdSBarry Smith    subset of exceptions may be trapable.
134e5c89e4eSSatish Balay 
135e5c89e4eSSatish Balay    Not Collective
136e5c89e4eSSatish Balay 
137e5c89e4eSSatish Balay    Input Parameters:
138cf0818bdSBarry Smith .  flag - values are
139cf0818bdSBarry Smith .vb
140cf0818bdSBarry Smith     PETSC_FP_TRAP_OFF   - do not trap any exceptions
141cf0818bdSBarry Smith     PETSC_FP_TRAP_ON - all exceptions that are possible on the system except underflow
142cf0818bdSBarry Smith     PETSC_FP_TRAP_INDIV - integer divide by zero
143cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTOPERR - improper argument to function, for example with real numbers, the square root of a negative number
144cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTOVF - overflow
145cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTUND - underflow - not trapped by default on most systems
146cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTDIV - floating point divide by zero
147cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTINEX - inexact floating point result
148cf0818bdSBarry Smith .ve
149e5c89e4eSSatish Balay 
150e5c89e4eSSatish Balay    Options Database Keys:
151cf0818bdSBarry Smith .  -fp_trap <off,on> - turn on or off trapping of floating point exceptions
152e5c89e4eSSatish Balay 
153e5c89e4eSSatish Balay    Level: advanced
154e5c89e4eSSatish Balay 
155cf0818bdSBarry Smith    Notes:
156cf0818bdSBarry Smith    Currently only PETSC_FP_TRAP_OFF and PETSC_FP_TRAP_ON are handled. All others are treated as PETSC_FP_TRAP_ON.
157cf0818bdSBarry Smith 
158cf0818bdSBarry Smith    The values are bit values and may be |ed together in the function call
159cf0818bdSBarry Smith 
160cf0818bdSBarry Smith    On systems that support it this routine causes floating point
161cf0818bdSBarry Smith    overflow, divide-by-zero, and invalid-operand (e.g., a NaN), but not underflow, to
162e5c89e4eSSatish Balay    cause a message to be printed and the program to exit.
163e5c89e4eSSatish Balay 
164cc9df77eSBarry Smith    On many common systems, the floating
1657d125cddSJed Brown    point exception state is not preserved from the location where the trap
1667d125cddSJed Brown    occurred through to the signal handler.  In this case, the signal handler
1677d125cddSJed Brown    will just say that an unknown floating point exception occurred and which
1687d125cddSJed Brown    function it occurred in.  If you run with -fp_trap in a debugger, it will
169cc9df77eSBarry Smith    break on the line where the error occurred.  On systems that support C99
170cc9df77eSBarry Smith    floating point exception handling You can check which
1717d125cddSJed Brown    exception occurred using fetestexcept(FE_ALL_EXCEPT).  See fenv.h
1727d125cddSJed Brown    (usually at /usr/include/bits/fenv.h) for the enum values on your system.
1737d125cddSJed Brown 
174e5c89e4eSSatish Balay    Caution:
175cc9df77eSBarry Smith    On certain machines, in particular the IBM PowerPC, floating point
176cc9df77eSBarry Smith    trapping may be VERY slow!
177e5c89e4eSSatish Balay 
178db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscFPTrapPop()`, `PetscDetermineInitialFPTrap()`
179e5c89e4eSSatish Balay @*/
1809371c9d4SSatish Balay PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) {
181e5c89e4eSSatish Balay   char *out;
182e5c89e4eSSatish Balay 
183e5c89e4eSSatish Balay   PetscFunctionBegin;
184e5c89e4eSSatish Balay   /* Clear accumulated exceptions.  Used to suppress meaningless messages from f77 programs */
185e5c89e4eSSatish Balay   (void)ieee_flags("clear", "exception", "all", &out);
186*bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
187e5c89e4eSSatish Balay     /*
188a297a907SKarl Rupp       To trap more fp exceptions, including underflow, change the line below to
189e5c89e4eSSatish Balay       if (ieee_handler("set","all",PetscDefaultFPTrap)) {
190e5c89e4eSSatish Balay     */
191a297a907SKarl Rupp     if (ieee_handler("set", "common", PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
192a297a907SKarl Rupp   } else if (ieee_handler("clear", "common", PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
193a297a907SKarl Rupp 
194670f3ff9SJed Brown   _trapmode = flag;
195*bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_SUN4_STYLE_FPTRAP\n"));
196e5c89e4eSSatish Balay   PetscFunctionReturn(0);
197e5c89e4eSSatish Balay }
198e5c89e4eSSatish Balay 
199cc9df77eSBarry Smith /*@
200aba4c478SBarry Smith    PetscDetermineInitialFPTrap - Attempts to determine the floating point trapping that exists when PetscInitialize() is called
201cc9df77eSBarry Smith 
202cc9df77eSBarry Smith    Not Collective
203cc9df77eSBarry Smith 
204cc9df77eSBarry Smith    Notes:
205cc9df77eSBarry Smith       Currently only supported on Linux and MacOS. Checks if divide by zero is enable and if so declares that trapping is on.
206cc9df77eSBarry Smith 
207ee300463SSatish Balay    Level: advanced
208cc9df77eSBarry Smith 
209db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscFPTrapPop()`, `PetscDetermineInitialFPTrap()`
210cc9df77eSBarry Smith @*/
2119371c9d4SSatish Balay PetscErrorCode PetscDetermineInitialFPTrap(void) {
212cc9df77eSBarry Smith   PetscFunctionBegin;
2139566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
214cc9df77eSBarry Smith   PetscFunctionReturn(0);
215cc9df77eSBarry Smith }
216cc9df77eSBarry Smith 
217e5c89e4eSSatish Balay /* -------------------------------------------------------------------------------------------*/
218e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP)
219e5c89e4eSSatish Balay #include <sunmath.h>
220e5c89e4eSSatish Balay #include <floatingpoint.h>
221e5c89e4eSSatish Balay #include <siginfo.h>
222e5c89e4eSSatish Balay #include <ucontext.h>
223e5c89e4eSSatish Balay 
2249371c9d4SSatish Balay static struct {
2259371c9d4SSatish Balay   int   code_no;
2269371c9d4SSatish Balay   char *name;
2279371c9d4SSatish Balay } error_codes[] = {
228e5c89e4eSSatish Balay   {FPE_FLTINV, "invalid floating point operand"},
229e5c89e4eSSatish Balay   {FPE_FLTRES, "inexact floating point result" },
230e5c89e4eSSatish Balay   {FPE_FLTDIV, "division-by-zero"              },
231e5c89e4eSSatish Balay   {FPE_FLTUND, "floating point underflow"      },
232e5c89e4eSSatish Balay   {FPE_FLTOVF, "floating point overflow"       },
233e5c89e4eSSatish Balay   {0,          "unknown error"                 }
234e5c89e4eSSatish Balay };
235e5c89e4eSSatish Balay #define SIGPC(scp) (scp->si_addr)
236e5c89e4eSSatish Balay 
2379371c9d4SSatish Balay void PetscDefaultFPTrap(int sig, siginfo_t *scp, ucontext_t *uap) {
2385f80ce2aSJacob Faibussowitsch   int err_ind = -1, code = scp->si_code;
239e5c89e4eSSatish Balay 
240e5c89e4eSSatish Balay   PetscFunctionBegin;
2415f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
242e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
243e5c89e4eSSatish Balay   }
244e5c89e4eSSatish Balay 
245a297a907SKarl Rupp   if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp));
246a297a907SKarl Rupp   else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp));
247a297a907SKarl Rupp 
24849c86fc7SBarry Smith   (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
24941e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
250e5c89e4eSSatish Balay }
251e5c89e4eSSatish Balay 
2529371c9d4SSatish Balay PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) {
253e5c89e4eSSatish Balay   char *out;
254e5c89e4eSSatish Balay 
255e5c89e4eSSatish Balay   PetscFunctionBegin;
256e5c89e4eSSatish Balay   /* Clear accumulated exceptions.  Used to suppress meaningless messages from f77 programs */
257e5c89e4eSSatish Balay   (void)ieee_flags("clear", "exception", "all", &out);
258e5c89e4eSSatish Balay   if (flag == PETSC_FP_TRAP_ON) {
259a297a907SKarl Rupp     if (ieee_handler("set", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n");
260cc9df77eSBarry Smith   } else {
261cc9df77eSBarry Smith     if (ieee_handler("clear", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
262cc9df77eSBarry Smith   }
263670f3ff9SJed Brown   _trapmode = flag;
264*bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL,"Using PETSC_HAVE_SOLARIS_STYLE_FPTRAP\n");
265e5c89e4eSSatish Balay   PetscFunctionReturn(0);
266e5c89e4eSSatish Balay }
267e5c89e4eSSatish Balay 
2689371c9d4SSatish Balay PetscErrorCode PetscDetermineInitialFPTrap(void) {
269cc9df77eSBarry Smith   PetscFunctionBegin;
2709566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
271cc9df77eSBarry Smith   PetscFunctionReturn(0);
272cc9df77eSBarry Smith }
273cc9df77eSBarry Smith 
274cc9df77eSBarry Smith /* ------------------------------------------------------------------------------------------*/
275e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_IRIX_STYLE_FPTRAP)
276e5c89e4eSSatish Balay #include <sigfpe.h>
2779371c9d4SSatish Balay static struct {
2789371c9d4SSatish Balay   int   code_no;
2799371c9d4SSatish Balay   char *name;
2809371c9d4SSatish Balay } error_codes[] = {
281e5c89e4eSSatish Balay   {_INVALID, "IEEE operand error"      },
282e5c89e4eSSatish Balay   {_OVERFL,  "floating point overflow" },
283e5c89e4eSSatish Balay   {_UNDERFL, "floating point underflow"},
284e5c89e4eSSatish Balay   {_DIVZERO, "floating point divide"   },
285e5c89e4eSSatish Balay   {0,        "unknown error"           }
286e5c89e4eSSatish Balay };
2879371c9d4SSatish Balay void PetscDefaultFPTrap(unsigned exception[], int val[]) {
2885f80ce2aSJacob Faibussowitsch   int err_ind = -1, code = exception[0];
289e5c89e4eSSatish Balay 
290e5c89e4eSSatish Balay   PetscFunctionBegin;
2915f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
292e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
293e5c89e4eSSatish Balay   }
294a297a907SKarl Rupp   if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name);
295a297a907SKarl Rupp   else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", code);
296a297a907SKarl Rupp 
29749c86fc7SBarry Smith   (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
29841e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
299e5c89e4eSSatish Balay }
300e5c89e4eSSatish Balay 
3019371c9d4SSatish Balay PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) {
302e5c89e4eSSatish Balay   PetscFunctionBegin;
303*bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) handle_sigfpes(_ON, , _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, PetscDefaultFPTrap, _ABORT_ON_ERROR, 0);
304cc9df77eSBarry Smith   else handle_sigfpes(_OFF, _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, 0, _ABORT_ON_ERROR, 0);
305670f3ff9SJed Brown   _trapmode = flag;
306*bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IRIX_STYLE_FPTRAP\n"));
307cc9df77eSBarry Smith   PetscFunctionReturn(0);
308cc9df77eSBarry Smith }
309cc9df77eSBarry Smith 
3109371c9d4SSatish Balay PetscErrorCode PetscDetermineInitialFPTrap(void) {
311cc9df77eSBarry Smith   PetscFunctionBegin;
3129566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
313cc9df77eSBarry Smith   PetscFunctionReturn(0);
314cc9df77eSBarry Smith }
315cc9df77eSBarry Smith 
316cc9df77eSBarry Smith /*----------------------------------------------- --------------------------------------------*/
317cc9df77eSBarry Smith #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP)
318e5c89e4eSSatish Balay /* In "fast" mode, floating point traps are imprecise and ignored.
319e5c89e4eSSatish Balay    This is the reason for the fptrap(FP_TRAP_SYNC) call */
320e5c89e4eSSatish Balay struct sigcontext;
321e5c89e4eSSatish Balay #include <fpxcp.h>
322e5c89e4eSSatish Balay #include <fptrap.h>
323e5c89e4eSSatish Balay #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000)
324e5c89e4eSSatish Balay #define FPE_FLTOVF_TRAP   (fptrap_t)(0x10000000)
325e5c89e4eSSatish Balay #define FPE_FLTUND_TRAP   (fptrap_t)(0x08000000)
326e5c89e4eSSatish Balay #define FPE_FLTDIV_TRAP   (fptrap_t)(0x04000000)
327e5c89e4eSSatish Balay #define FPE_FLTINEX_TRAP  (fptrap_t)(0x02000000)
328e5c89e4eSSatish Balay 
3299371c9d4SSatish Balay static struct {
3309371c9d4SSatish Balay   int   code_no;
3319371c9d4SSatish Balay   char *name;
3329371c9d4SSatish Balay } error_codes[] = {
333e5c89e4eSSatish Balay   {FPE_FLTOPERR_TRAP, "IEEE operand error"           },
334e5c89e4eSSatish Balay   {FPE_FLTOVF_TRAP,   "floating point overflow"      },
335e5c89e4eSSatish Balay   {FPE_FLTUND_TRAP,   "floating point underflow"     },
336e5c89e4eSSatish Balay   {FPE_FLTDIV_TRAP,   "floating point divide"        },
337e5c89e4eSSatish Balay   {FPE_FLTINEX_TRAP,  "inexact floating point result"},
338*bd2b07b1SBarry Smith   < {0,                 "unknown error"                }
339e5c89e4eSSatish Balay };
340e5c89e4eSSatish Balay #define SIGPC(scp)        (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */
341e5c89e4eSSatish Balay /*
342e5c89e4eSSatish Balay    For some reason, scp->sc_jmpbuf does not work on the RS6000, even though
343e5c89e4eSSatish Balay    it looks like it should from the include definitions.  It is probably
344e5c89e4eSSatish Balay    some strange interaction with the "POSIX_SOURCE" that we require.
345e5c89e4eSSatish Balay */
346e5c89e4eSSatish Balay 
3479371c9d4SSatish Balay void PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp) {
348e5c89e4eSSatish Balay   int      err_ind, j;
349e5c89e4eSSatish Balay   fp_ctx_t flt_context;
350e5c89e4eSSatish Balay 
351e5c89e4eSSatish Balay   PetscFunctionBegin;
352e5c89e4eSSatish Balay   fp_sh_trap_info(scp, &flt_context);
353e5c89e4eSSatish Balay 
354e5c89e4eSSatish Balay   err_ind = -1;
355e5c89e4eSSatish Balay   for (j = 0; error_codes[j].code_no; j++) {
356e5c89e4eSSatish Balay     if (error_codes[j].code_no == flt_context.trap) err_ind = j;
357e5c89e4eSSatish Balay   }
358e5c89e4eSSatish Balay 
359a297a907SKarl Rupp   if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name);
360a297a907SKarl Rupp   else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", flt_context.trap);
361a297a907SKarl Rupp 
36249c86fc7SBarry Smith   (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
36341e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
364e5c89e4eSSatish Balay }
365e5c89e4eSSatish Balay 
3669371c9d4SSatish Balay PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) {
367e5c89e4eSSatish Balay   PetscFunctionBegin;
368*bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
369e5c89e4eSSatish Balay     signal(SIGFPE, (void (*)(int))PetscDefaultFPTrap);
370e5c89e4eSSatish Balay     fp_trap(FP_TRAP_SYNC);
371*bd2b07b1SBarry Smith     /* fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); */
372*bd2b07b1SBarry Smith     fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
373e5c89e4eSSatish Balay   } else {
374e5c89e4eSSatish Balay     signal(SIGFPE, SIG_DFL);
375cc9df77eSBarry Smith     fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW);
376e5c89e4eSSatish Balay     fp_trap(FP_TRAP_OFF);
377e5c89e4eSSatish Balay   }
378cf0818bdSBarry Smith   _trapmode = flag;
379*bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_RS6000_STYLE_FPTRAP\n"));
380e5c89e4eSSatish Balay   PetscFunctionReturn(0);
381e5c89e4eSSatish Balay }
382e5c89e4eSSatish Balay 
3839371c9d4SSatish Balay PetscErrorCode PetscDetermineInitialFPTrap(void) {
384cc9df77eSBarry Smith   PetscFunctionBegin;
3859566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
386cc9df77eSBarry Smith   PetscFunctionReturn(0);
387cc9df77eSBarry Smith }
388cc9df77eSBarry Smith 
389cc9df77eSBarry Smith /* ------------------------------------------------------------*/
390cc9df77eSBarry Smith #elif defined(PETSC_HAVE_WINDOWS_COMPILERS)
391cc9df77eSBarry Smith #include <float.h>
3929371c9d4SSatish Balay void PetscDefaultFPTrap(int sig) {
393cc9df77eSBarry Smith   PetscFunctionBegin;
394cc9df77eSBarry Smith   (*PetscErrorPrintf)("*** floating point error occurred ***\n");
39549c86fc7SBarry Smith   PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
396cc9df77eSBarry Smith   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
397cc9df77eSBarry Smith }
398cc9df77eSBarry Smith 
3999371c9d4SSatish Balay PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) {
400cc9df77eSBarry Smith   unsigned int cw;
401cc9df77eSBarry Smith 
402cc9df77eSBarry Smith   PetscFunctionBegin;
403*bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
404*bd2b07b1SBarry Smith     /* cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW; */
405*bd2b07b1SBarry Smith     cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW;
40608401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
407cc9df77eSBarry Smith   } else {
408cc9df77eSBarry Smith     cw = 0;
40908401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
410cc9df77eSBarry Smith   }
411cc9df77eSBarry Smith   (void)_controlfp(0, cw);
412cf0818bdSBarry Smith   _trapmode = flag;
413*bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_WINDOWS_COMPILERS FPTRAP\n"));
414cc9df77eSBarry Smith   PetscFunctionReturn(0);
415cc9df77eSBarry Smith }
416cc9df77eSBarry Smith 
4179371c9d4SSatish Balay PetscErrorCode PetscDetermineInitialFPTrap(void) {
418cc9df77eSBarry Smith   PetscFunctionBegin;
4199566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
420cc9df77eSBarry Smith   PetscFunctionReturn(0);
421cc9df77eSBarry Smith }
422cc9df77eSBarry Smith 
423cc9df77eSBarry Smith /* ------------------------------------------------------------*/
4249a2402e9SBarry Smith #elif defined(PETSC_HAVE_FENV_H) && !defined(__cplusplus)
425b014e56cSJed Brown /*
426b014e56cSJed Brown    C99 style floating point environment.
427b014e56cSJed Brown 
428b014e56cSJed Brown    Note that C99 merely specifies how to save, restore, and clear the floating
429b014e56cSJed Brown    point environment as well as defining an enumeration of exception codes.  In
430b014e56cSJed Brown    particular, C99 does not specify how to make floating point exceptions raise
431b014e56cSJed Brown    a signal.  Glibc offers this capability through FE_NOMASK_ENV (or with finer
432b014e56cSJed Brown    granularity, feenableexcept()), xmmintrin.h offers _MM_SET_EXCEPTION_MASK().
433b014e56cSJed Brown */
434b014e56cSJed Brown #include <fenv.h>
4359371c9d4SSatish Balay typedef struct {
4369371c9d4SSatish Balay   int         code;
4379371c9d4SSatish Balay   const char *name;
4389371c9d4SSatish Balay } FPNode;
439b014e56cSJed Brown static const FPNode error_codes[] = {
440b014e56cSJed Brown   {FE_DIVBYZERO, "divide by zero"                                 },
441b014e56cSJed Brown   {FE_INEXACT,   "inexact floating point result"                  },
442b014e56cSJed Brown   {FE_INVALID,   "invalid floating point arguments (domain error)"},
443b014e56cSJed Brown   {FE_OVERFLOW,  "floating point overflow"                        },
444b014e56cSJed Brown   {FE_UNDERFLOW, "floating point underflow"                       },
445b014e56cSJed Brown   {0,            "unknown error"                                  }
446b014e56cSJed Brown };
44799e0435eSBarry Smith 
4489371c9d4SSatish Balay void PetscDefaultFPTrap(int sig) {
449b014e56cSJed Brown   const FPNode *node;
450b014e56cSJed Brown   int           code;
451ace3abfcSBarry Smith   PetscBool     matched = PETSC_FALSE;
452b014e56cSJed Brown 
453b014e56cSJed Brown   PetscFunctionBegin;
454b014e56cSJed Brown   /* Note: While it is possible for the exception state to be preserved by the
455b014e56cSJed Brown    * kernel, this seems to be rare which makes the following flag testing almost
456b014e56cSJed Brown    * useless.  But on a system where the flags can be preserved, it would provide
4577d125cddSJed Brown    * more detail.
458b014e56cSJed Brown    */
459b014e56cSJed Brown   code = fetestexcept(FE_ALL_EXCEPT);
460b014e56cSJed Brown   for (node = &error_codes[0]; node->code; node++) {
461b014e56cSJed Brown     if (code & node->code) {
462b014e56cSJed Brown       matched = PETSC_TRUE;
463b014e56cSJed Brown       (*PetscErrorPrintf)("*** floating point error \"%s\" occurred ***\n", node->name);
464b014e56cSJed Brown       code &= ~node->code; /* Unset this flag since it has been processed */
465b014e56cSJed Brown     }
466b014e56cSJed Brown   }
467b014e56cSJed Brown   if (!matched || code) { /* If any remaining flags are set, or we didn't process any flags */
468b014e56cSJed Brown     (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n");
4697d125cddSJed Brown     (*PetscErrorPrintf)("The specific exception can be determined by running in a debugger.  When the\n");
4707d125cddSJed Brown     (*PetscErrorPrintf)("debugger traps the signal, the exception can be found with fetestexcept(0x%x)\n", FE_ALL_EXCEPT);
4717d125cddSJed Brown     (*PetscErrorPrintf)("where the result is a bitwise OR of the following flags:\n");
4727d125cddSJed Brown     (*PetscErrorPrintf)("FE_INVALID=0x%x FE_DIVBYZERO=0x%x FE_OVERFLOW=0x%x FE_UNDERFLOW=0x%x FE_INEXACT=0x%x\n", FE_INVALID, FE_DIVBYZERO, FE_OVERFLOW, FE_UNDERFLOW, FE_INEXACT);
473b014e56cSJed Brown   }
4747d125cddSJed Brown 
4757d125cddSJed Brown   (*PetscErrorPrintf)("Try option -start_in_debugger\n");
47627104ee2SJacob Faibussowitsch #if PetscDefined(USE_DEBUG)
4777d125cddSJed Brown   (*PetscErrorPrintf)("likely location of problem given in stack below\n");
4787d125cddSJed Brown   (*PetscErrorPrintf)("---------------------  Stack Frames ------------------------------------\n");
479639ff905SBarry Smith   PetscStackView(PETSC_STDOUT);
48027104ee2SJacob Faibussowitsch #else
4817d125cddSJed Brown   (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
4827d125cddSJed Brown   (*PetscErrorPrintf)("with -start_in_debugger to get more information on the crash.\n");
48327104ee2SJacob Faibussowitsch #endif
48449c86fc7SBarry Smith   PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_INITIAL, "trapped floating point error");
48541e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
486b014e56cSJed Brown }
487b014e56cSJed Brown 
4889371c9d4SSatish Balay PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) {
489b014e56cSJed Brown   PetscFunctionBegin;
490*bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
491b014e56cSJed Brown     /* Clear any flags that are currently set so that activating trapping will not immediately call the signal handler. */
492cc73adaaSBarry Smith     PetscCheck(!feclearexcept(FE_ALL_EXCEPT), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot clear floating point exception flags");
493cc9df77eSBarry Smith #if defined(FE_NOMASK_ENV)
494cc9df77eSBarry Smith     /* Could use fesetenv(FE_NOMASK_ENV), but that causes spurious exceptions (like gettimeofday() -> PetscLogDouble). */
495cf0818bdSBarry Smith     /* PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) != -1,PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot activate floating point exceptions"); */
496*bd2b07b1SBarry Smith     /* Doesn't work on AArch64 targets. There's a known hardware limitation. Need to detect hardware at configure time? */
497cf0818bdSBarry Smith     PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW) != -1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot activate floating point exceptions");
498*bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with FE_NOMASK_ENV\n"));
499b014e56cSJed Brown #elif defined PETSC_HAVE_XMMINTRIN_H
500cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_DIV_ZERO);
501*bd2b07b1SBarry Smith     /* _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_UNDERFLOW); */
502cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_OVERFLOW);
503cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID);
504*bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with PETSC_HAVE_XMMINTRIN_H\n"));
505b014e56cSJed Brown #else
506b014e56cSJed Brown     /* C99 does not provide a way to modify the environment so there is no portable way to activate trapping. */
507*bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP\n"));
508b014e56cSJed Brown #endif
50908401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
510b014e56cSJed Brown   } else {
511cc73adaaSBarry Smith     PetscCheck(!fesetenv(FE_DFL_ENV), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot disable floating point exceptions");
512cc9df77eSBarry Smith     /* can use _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | _MM_MASK_UNDERFLOW); if PETSC_HAVE_XMMINTRIN_H exists */
51308401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
514b014e56cSJed Brown   }
515cf0818bdSBarry Smith   _trapmode = flag;
516b014e56cSJed Brown   PetscFunctionReturn(0);
517b014e56cSJed Brown }
518b014e56cSJed Brown 
5199371c9d4SSatish Balay PetscErrorCode PetscDetermineInitialFPTrap(void) {
520cc9df77eSBarry Smith #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
521cc9df77eSBarry Smith   unsigned int flags;
522cc9df77eSBarry Smith #endif
523cc9df77eSBarry Smith 
524cc9df77eSBarry Smith   PetscFunctionBegin;
525cc9df77eSBarry Smith #if defined(FE_NOMASK_ENV)
526cc9df77eSBarry Smith   flags = fegetexcept();
527cc9df77eSBarry Smith   if (flags & FE_DIVBYZERO) {
528cc9df77eSBarry Smith #elif defined PETSC_HAVE_XMMINTRIN_H
529cc9df77eSBarry Smith   flags = _MM_GET_EXCEPTION_MASK();
530cc9df77eSBarry Smith   if (!(flags & _MM_MASK_DIV_ZERO)) {
531cc9df77eSBarry Smith #else
5329566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Floating point trapping unknown, assuming off\n"));
533cc9df77eSBarry Smith   PetscFunctionReturn(0);
534cc9df77eSBarry Smith #endif
535cc9df77eSBarry Smith #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
536cc9df77eSBarry Smith     _trapmode = PETSC_FP_TRAP_ON;
5379566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Floating point trapping is on by default %d\n", flags));
538cc9df77eSBarry Smith   } else {
539cc9df77eSBarry Smith     _trapmode = PETSC_FP_TRAP_OFF;
5409566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Floating point trapping is off by default %d\n", flags));
541cc9df77eSBarry Smith   }
542cc9df77eSBarry Smith   PetscFunctionReturn(0);
543cc9df77eSBarry Smith #endif
544cc9df77eSBarry Smith }
545cc9df77eSBarry Smith 
546cc9df77eSBarry Smith /* ------------------------------------------------------------*/
547cc9df77eSBarry Smith #elif defined(PETSC_HAVE_IEEEFP_H)
548cc9df77eSBarry Smith #include <ieeefp.h>
5499371c9d4SSatish Balay void PetscDefaultFPTrap(int sig) {
550cc9df77eSBarry Smith   PetscFunctionBegin;
551cc9df77eSBarry Smith   (*PetscErrorPrintf)("*** floating point error occurred ***\n");
55249c86fc7SBarry Smith   PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
553cc9df77eSBarry Smith   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
554cc9df77eSBarry Smith }
555cc9df77eSBarry Smith 
5569371c9d4SSatish Balay PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) {
557cc9df77eSBarry Smith   PetscFunctionBegin;
558cf0818bdSBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
559cc9df77eSBarry Smith #if defined(PETSC_HAVE_FPPRESETSTICKY)
560cc9df77eSBarry Smith     fpresetsticky(fpgetsticky());
561cc9df77eSBarry Smith #elif defined(PETSC_HAVE_FPSETSTICKY)
562cc9df77eSBarry Smith     fpsetsticky(fpgetsticky());
563cc9df77eSBarry Smith #endif
564cc9df77eSBarry Smith     fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_OFL);
56508401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
566cc9df77eSBarry Smith   } else {
567cc9df77eSBarry Smith #if defined(PETSC_HAVE_FPPRESETSTICKY)
568cc9df77eSBarry Smith     fpresetsticky(fpgetsticky());
569cc9df77eSBarry Smith #elif defined(PETSC_HAVE_FPSETSTICKY)
570cc9df77eSBarry Smith     fpsetsticky(fpgetsticky());
571cc9df77eSBarry Smith #endif
572cc9df77eSBarry Smith     fpsetmask(0);
57308401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
574cc9df77eSBarry Smith   }
575cf0818bdSBarry Smith   _trapmode = flag;
576*bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IEEEFP_H FPTRAP\n"));
577cc9df77eSBarry Smith   PetscFunctionReturn(0);
578cc9df77eSBarry Smith }
579cc9df77eSBarry Smith 
5809371c9d4SSatish Balay PetscErrorCode PetscDetermineInitialFPTrap(void) {
581cc9df77eSBarry Smith   PetscFunctionBegin;
5829566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
583cc9df77eSBarry Smith   PetscFunctionReturn(0);
584cc9df77eSBarry Smith }
585cc9df77eSBarry Smith 
586e5c89e4eSSatish Balay /* -------------------------Default -----------------------------------*/
587e5c89e4eSSatish Balay #else
58899e0435eSBarry Smith 
5899371c9d4SSatish Balay void PetscDefaultFPTrap(int sig) {
590e5c89e4eSSatish Balay   PetscFunctionBegin;
591e5c89e4eSSatish Balay   (*PetscErrorPrintf)("*** floating point error occurred ***\n");
59249c86fc7SBarry Smith   PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
59341e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
594e5c89e4eSSatish Balay }
59599e0435eSBarry Smith 
5969371c9d4SSatish Balay PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) {
597e5c89e4eSSatish Balay   PetscFunctionBegin;
598*bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
599a297a907SKarl Rupp     if (SIG_ERR == signal(SIGFPE, PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
600a297a907SKarl Rupp   } else if (SIG_ERR == signal(SIGFPE, SIG_DFL)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
601a297a907SKarl Rupp 
602cf0818bdSBarry Smith   _trapmode = flag;
603*bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using default FPTRAP\n"));
604e5c89e4eSSatish Balay   PetscFunctionReturn(0);
605e5c89e4eSSatish Balay }
606cc9df77eSBarry Smith 
6079371c9d4SSatish Balay PetscErrorCode PetscDetermineInitialFPTrap(void) {
608cc9df77eSBarry Smith   PetscFunctionBegin;
6099566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
610cc9df77eSBarry Smith   PetscFunctionReturn(0);
611cc9df77eSBarry Smith }
612e5c89e4eSSatish Balay #endif
613