xref: /petsc/src/sys/error/fp.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
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 /*@
29811af0c4SBarry Smith    PetscFPTrapPush - push a floating point trapping mode, restored using `PetscFPTrapPop()`
30670f3ff9SJed Brown 
31670f3ff9SJed Brown    Not Collective
32670f3ff9SJed Brown 
334165533cSJose E. Roman    Input Parameter:
34811af0c4SBarry 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 @*/
51*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPTrapPush(PetscFPTrap trap)
52*d71ae5a4SJacob Faibussowitsch {
53670f3ff9SJed Brown   struct PetscFPTrapLink *link;
54670f3ff9SJed Brown 
55670f3ff9SJed Brown   PetscFunctionBegin;
569566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
571f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP)
581f006be4SPierre Jolivet   #pragma omp critical
591f006be4SPierre Jolivet #endif
601f006be4SPierre Jolivet   {
61670f3ff9SJed Brown     link->trapmode = _trapmode;
62670f3ff9SJed Brown     link->next     = _trapstack;
63670f3ff9SJed Brown     _trapstack     = link;
641f006be4SPierre Jolivet   }
659566063dSJacob Faibussowitsch   if (trap != _trapmode) PetscCall(PetscSetFPTrap(trap));
66670f3ff9SJed Brown   PetscFunctionReturn(0);
67670f3ff9SJed Brown }
68670f3ff9SJed Brown 
69670f3ff9SJed Brown /*@
70811af0c4SBarry Smith    PetscFPTrapPop - push a floating point trapping mode, to be restored using `PetscFPTrapPop()`
71670f3ff9SJed Brown 
72670f3ff9SJed Brown    Not Collective
73670f3ff9SJed Brown 
74670f3ff9SJed Brown    Level: advanced
75670f3ff9SJed Brown 
76db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscSetFPTrap()`, `PetscDetermineInitialFPTrap()`
77670f3ff9SJed Brown @*/
78*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPTrapPop(void)
79*d71ae5a4SJacob Faibussowitsch {
80670f3ff9SJed Brown   struct PetscFPTrapLink *link;
81670f3ff9SJed Brown 
82670f3ff9SJed Brown   PetscFunctionBegin;
839566063dSJacob Faibussowitsch   if (_trapstack->trapmode != _trapmode) PetscCall(PetscSetFPTrap(_trapstack->trapmode));
841f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP)
851f006be4SPierre Jolivet   #pragma omp critical
861f006be4SPierre Jolivet #endif
871f006be4SPierre Jolivet   {
88670f3ff9SJed Brown     link       = _trapstack;
89670f3ff9SJed Brown     _trapstack = _trapstack->next;
901f006be4SPierre Jolivet   }
919566063dSJacob Faibussowitsch   PetscCall(PetscFree(link));
92670f3ff9SJed Brown   PetscFunctionReturn(0);
93670f3ff9SJed Brown }
94670f3ff9SJed Brown 
95e5c89e4eSSatish Balay /*--------------------------------------- ---------------------------------------------------*/
96e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP)
97e5c89e4eSSatish Balay   #include <floatingpoint.h>
98e5c89e4eSSatish Balay 
998cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_flags(char *, char *, char *, char **);
1008cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_handler(char *, char *, sigfpe_handler_type(int, int, struct sigcontext *, char *));
101e5c89e4eSSatish Balay 
1029371c9d4SSatish Balay static struct {
1039371c9d4SSatish Balay   int   code_no;
1049371c9d4SSatish Balay   char *name;
1059371c9d4SSatish Balay } error_codes[] = {
106e5c89e4eSSatish Balay   {FPE_INTDIV_TRAP,   "integer divide"               },
107e5c89e4eSSatish Balay   {FPE_FLTOPERR_TRAP, "IEEE operand error"           },
108e5c89e4eSSatish Balay   {FPE_FLTOVF_TRAP,   "floating point overflow"      },
109e5c89e4eSSatish Balay   {FPE_FLTUND_TRAP,   "floating point underflow"     },
110e5c89e4eSSatish Balay   {FPE_FLTDIV_TRAP,   "floating pointing divide"     },
111e5c89e4eSSatish Balay   {FPE_FLTINEX_TRAP,  "inexact floating point result"},
112e5c89e4eSSatish Balay   {0,                 "unknown error"                }
113e5c89e4eSSatish Balay };
114e5c89e4eSSatish Balay   #define SIGPC(scp) (scp->sc_pc)
115e5c89e4eSSatish Balay 
116cf0818bdSBarry Smith /* this function gets called if a trap has occurred and been caught */
117*d71ae5a4SJacob Faibussowitsch sigfpe_handler_type PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp, char *addr)
118*d71ae5a4SJacob Faibussowitsch {
1195f80ce2aSJacob Faibussowitsch   int err_ind = -1;
120e5c89e4eSSatish Balay 
121e5c89e4eSSatish Balay   PetscFunctionBegin;
1225f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
123e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
124e5c89e4eSSatish Balay   }
125e5c89e4eSSatish Balay 
126a297a907SKarl Rupp   if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp));
127a297a907SKarl Rupp   else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp));
128a297a907SKarl Rupp 
12949c86fc7SBarry Smith   (void)PetscError(PETSC_COMM_SELF, PETSC_ERR_FP, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
13041e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
131e5c89e4eSSatish Balay   PetscFunctionReturn(0);
132e5c89e4eSSatish Balay }
133e5c89e4eSSatish Balay 
134e30d2299SSatish Balay /*@
135cf0818bdSBarry Smith    PetscSetFPTrap - Enables traps/exceptions on common floating point errors. This option may not work on certain systems or only a
136cf0818bdSBarry Smith    subset of exceptions may be trapable.
137e5c89e4eSSatish Balay 
138e5c89e4eSSatish Balay    Not Collective
139e5c89e4eSSatish Balay 
140e5c89e4eSSatish Balay    Input Parameters:
141cf0818bdSBarry Smith .  flag - values are
142cf0818bdSBarry Smith .vb
143cf0818bdSBarry Smith     PETSC_FP_TRAP_OFF   - do not trap any exceptions
144cf0818bdSBarry Smith     PETSC_FP_TRAP_ON - all exceptions that are possible on the system except underflow
145cf0818bdSBarry Smith     PETSC_FP_TRAP_INDIV - integer divide by zero
146cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTOPERR - improper argument to function, for example with real numbers, the square root of a negative number
147cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTOVF - overflow
148cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTUND - underflow - not trapped by default on most systems
149cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTDIV - floating point divide by zero
150cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTINEX - inexact floating point result
151cf0818bdSBarry Smith .ve
152e5c89e4eSSatish Balay 
153e5c89e4eSSatish Balay    Options Database Keys:
154cf0818bdSBarry Smith .  -fp_trap <off,on> - turn on or off trapping of floating point exceptions
155e5c89e4eSSatish Balay 
156e5c89e4eSSatish Balay    Level: advanced
157e5c89e4eSSatish Balay 
158cf0818bdSBarry Smith    Notes:
159811af0c4SBarry Smith    Currently only `PETSC_FP_TRAP_OFF` and `PETSC_FP_TRAP_ON` are handled. All others are treated as `PETSC_FP_TRAP_ON`.
160cf0818bdSBarry Smith 
161cf0818bdSBarry Smith    The values are bit values and may be |ed together in the function call
162cf0818bdSBarry Smith 
163cf0818bdSBarry Smith    On systems that support it this routine causes floating point
164cf0818bdSBarry Smith    overflow, divide-by-zero, and invalid-operand (e.g., a NaN), but not underflow, to
165e5c89e4eSSatish Balay    cause a message to be printed and the program to exit.
166e5c89e4eSSatish Balay 
167cc9df77eSBarry Smith    On many common systems, the floating
1687d125cddSJed Brown    point exception state is not preserved from the location where the trap
1697d125cddSJed Brown    occurred through to the signal handler.  In this case, the signal handler
1707d125cddSJed Brown    will just say that an unknown floating point exception occurred and which
1717d125cddSJed Brown    function it occurred in.  If you run with -fp_trap in a debugger, it will
172cc9df77eSBarry Smith    break on the line where the error occurred.  On systems that support C99
173cc9df77eSBarry Smith    floating point exception handling You can check which
1747d125cddSJed Brown    exception occurred using fetestexcept(FE_ALL_EXCEPT).  See fenv.h
1757d125cddSJed Brown    (usually at /usr/include/bits/fenv.h) for the enum values on your system.
1767d125cddSJed Brown 
177db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscFPTrapPop()`, `PetscDetermineInitialFPTrap()`
178e5c89e4eSSatish Balay @*/
179*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
180*d71ae5a4SJacob Faibussowitsch {
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);
186bd2b07b1SBarry 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;
195bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_SUN4_STYLE_FPTRAP\n"));
196e5c89e4eSSatish Balay   PetscFunctionReturn(0);
197e5c89e4eSSatish Balay }
198e5c89e4eSSatish Balay 
199cc9df77eSBarry Smith /*@
200811af0c4SBarry Smith    PetscDetermineInitialFPTrap - Attempts to determine the floating point trapping that exists when `PetscInitialize()` is called
201cc9df77eSBarry Smith 
202cc9df77eSBarry Smith    Not Collective
203cc9df77eSBarry Smith 
204811af0c4SBarry Smith    Note:
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 @*/
211*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
212*d71ae5a4SJacob Faibussowitsch {
213cc9df77eSBarry Smith   PetscFunctionBegin;
2149566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
215cc9df77eSBarry Smith   PetscFunctionReturn(0);
216cc9df77eSBarry Smith }
217cc9df77eSBarry Smith 
218e5c89e4eSSatish Balay /* -------------------------------------------------------------------------------------------*/
219e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP)
220e5c89e4eSSatish Balay   #include <sunmath.h>
221e5c89e4eSSatish Balay   #include <floatingpoint.h>
222e5c89e4eSSatish Balay   #include <siginfo.h>
223e5c89e4eSSatish Balay   #include <ucontext.h>
224e5c89e4eSSatish Balay 
2259371c9d4SSatish Balay static struct {
2269371c9d4SSatish Balay   int   code_no;
2279371c9d4SSatish Balay   char *name;
2289371c9d4SSatish Balay } error_codes[] = {
229e5c89e4eSSatish Balay   {FPE_FLTINV, "invalid floating point operand"},
230e5c89e4eSSatish Balay   {FPE_FLTRES, "inexact floating point result" },
231e5c89e4eSSatish Balay   {FPE_FLTDIV, "division-by-zero"              },
232e5c89e4eSSatish Balay   {FPE_FLTUND, "floating point underflow"      },
233e5c89e4eSSatish Balay   {FPE_FLTOVF, "floating point overflow"       },
234e5c89e4eSSatish Balay   {0,          "unknown error"                 }
235e5c89e4eSSatish Balay };
236e5c89e4eSSatish Balay   #define SIGPC(scp) (scp->si_addr)
237e5c89e4eSSatish Balay 
238*d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig, siginfo_t *scp, ucontext_t *uap)
239*d71ae5a4SJacob Faibussowitsch {
2405f80ce2aSJacob Faibussowitsch   int err_ind = -1, code = scp->si_code;
241e5c89e4eSSatish Balay 
242e5c89e4eSSatish Balay   PetscFunctionBegin;
2435f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
244e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
245e5c89e4eSSatish Balay   }
246e5c89e4eSSatish Balay 
247a297a907SKarl Rupp   if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp));
248a297a907SKarl Rupp   else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp));
249a297a907SKarl Rupp 
25049c86fc7SBarry Smith   (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
25141e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
252e5c89e4eSSatish Balay }
253e5c89e4eSSatish Balay 
254*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
255*d71ae5a4SJacob Faibussowitsch {
256e5c89e4eSSatish Balay   char *out;
257e5c89e4eSSatish Balay 
258e5c89e4eSSatish Balay   PetscFunctionBegin;
259e5c89e4eSSatish Balay   /* Clear accumulated exceptions.  Used to suppress meaningless messages from f77 programs */
260e5c89e4eSSatish Balay   (void)ieee_flags("clear", "exception", "all", &out);
261e5c89e4eSSatish Balay   if (flag == PETSC_FP_TRAP_ON) {
262a297a907SKarl Rupp     if (ieee_handler("set", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n");
263cc9df77eSBarry Smith   } else {
264cc9df77eSBarry Smith     if (ieee_handler("clear", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
265cc9df77eSBarry Smith   }
266670f3ff9SJed Brown   _trapmode = flag;
267bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL,"Using PETSC_HAVE_SOLARIS_STYLE_FPTRAP\n");
268e5c89e4eSSatish Balay   PetscFunctionReturn(0);
269e5c89e4eSSatish Balay }
270e5c89e4eSSatish Balay 
271*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
272*d71ae5a4SJacob Faibussowitsch {
273cc9df77eSBarry Smith   PetscFunctionBegin;
2749566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
275cc9df77eSBarry Smith   PetscFunctionReturn(0);
276cc9df77eSBarry Smith }
277cc9df77eSBarry Smith 
278cc9df77eSBarry Smith /* ------------------------------------------------------------------------------------------*/
279e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_IRIX_STYLE_FPTRAP)
280e5c89e4eSSatish Balay   #include <sigfpe.h>
2819371c9d4SSatish Balay static struct {
2829371c9d4SSatish Balay   int   code_no;
2839371c9d4SSatish Balay   char *name;
2849371c9d4SSatish Balay } error_codes[] = {
285e5c89e4eSSatish Balay   {_INVALID, "IEEE operand error"      },
286e5c89e4eSSatish Balay   {_OVERFL,  "floating point overflow" },
287e5c89e4eSSatish Balay   {_UNDERFL, "floating point underflow"},
288e5c89e4eSSatish Balay   {_DIVZERO, "floating point divide"   },
289e5c89e4eSSatish Balay   {0,        "unknown error"           }
290e5c89e4eSSatish Balay };
291*d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(unsigned exception[], int val[])
292*d71ae5a4SJacob Faibussowitsch {
2935f80ce2aSJacob Faibussowitsch   int err_ind = -1, code = exception[0];
294e5c89e4eSSatish Balay 
295e5c89e4eSSatish Balay   PetscFunctionBegin;
2965f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
297e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
298e5c89e4eSSatish Balay   }
299a297a907SKarl Rupp   if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name);
300a297a907SKarl Rupp   else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", code);
301a297a907SKarl Rupp 
30249c86fc7SBarry Smith   (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
30341e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
304e5c89e4eSSatish Balay }
305e5c89e4eSSatish Balay 
306*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
307*d71ae5a4SJacob Faibussowitsch {
308e5c89e4eSSatish Balay   PetscFunctionBegin;
309bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) handle_sigfpes(_ON, , _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, PetscDefaultFPTrap, _ABORT_ON_ERROR, 0);
310cc9df77eSBarry Smith   else handle_sigfpes(_OFF, _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, 0, _ABORT_ON_ERROR, 0);
311670f3ff9SJed Brown   _trapmode = flag;
312bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IRIX_STYLE_FPTRAP\n"));
313cc9df77eSBarry Smith   PetscFunctionReturn(0);
314cc9df77eSBarry Smith }
315cc9df77eSBarry Smith 
316*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
317*d71ae5a4SJacob Faibussowitsch {
318cc9df77eSBarry Smith   PetscFunctionBegin;
3199566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
320cc9df77eSBarry Smith   PetscFunctionReturn(0);
321cc9df77eSBarry Smith }
322cc9df77eSBarry Smith 
323cc9df77eSBarry Smith /*----------------------------------------------- --------------------------------------------*/
324cc9df77eSBarry Smith #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP)
325e5c89e4eSSatish Balay /* In "fast" mode, floating point traps are imprecise and ignored.
326e5c89e4eSSatish Balay    This is the reason for the fptrap(FP_TRAP_SYNC) call */
327e5c89e4eSSatish Balay struct sigcontext;
328e5c89e4eSSatish Balay   #include <fpxcp.h>
329e5c89e4eSSatish Balay   #include <fptrap.h>
330e5c89e4eSSatish Balay   #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000)
331e5c89e4eSSatish Balay   #define FPE_FLTOVF_TRAP   (fptrap_t)(0x10000000)
332e5c89e4eSSatish Balay   #define FPE_FLTUND_TRAP   (fptrap_t)(0x08000000)
333e5c89e4eSSatish Balay   #define FPE_FLTDIV_TRAP   (fptrap_t)(0x04000000)
334e5c89e4eSSatish Balay   #define FPE_FLTINEX_TRAP  (fptrap_t)(0x02000000)
335e5c89e4eSSatish Balay 
3369371c9d4SSatish Balay static struct {
3379371c9d4SSatish Balay   int   code_no;
3389371c9d4SSatish Balay   char *name;
3399371c9d4SSatish Balay } error_codes[] = {
340e5c89e4eSSatish Balay   {FPE_FLTOPERR_TRAP, "IEEE operand error"           },
341e5c89e4eSSatish Balay   {FPE_FLTOVF_TRAP,   "floating point overflow"      },
342e5c89e4eSSatish Balay   {FPE_FLTUND_TRAP,   "floating point underflow"     },
343e5c89e4eSSatish Balay   {FPE_FLTDIV_TRAP,   "floating point divide"        },
344e5c89e4eSSatish Balay   {FPE_FLTINEX_TRAP,  "inexact floating point result"},
345bd2b07b1SBarry Smith   < {0,                 "unknown error"                }
346e5c89e4eSSatish Balay };
347e5c89e4eSSatish Balay   #define SIGPC(scp)        (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */
348e5c89e4eSSatish Balay /*
349e5c89e4eSSatish Balay    For some reason, scp->sc_jmpbuf does not work on the RS6000, even though
350e5c89e4eSSatish Balay    it looks like it should from the include definitions.  It is probably
351e5c89e4eSSatish Balay    some strange interaction with the "POSIX_SOURCE" that we require.
352e5c89e4eSSatish Balay */
353e5c89e4eSSatish Balay 
354*d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp)
355*d71ae5a4SJacob Faibussowitsch {
356e5c89e4eSSatish Balay   int      err_ind, j;
357e5c89e4eSSatish Balay   fp_ctx_t flt_context;
358e5c89e4eSSatish Balay 
359e5c89e4eSSatish Balay   PetscFunctionBegin;
360e5c89e4eSSatish Balay   fp_sh_trap_info(scp, &flt_context);
361e5c89e4eSSatish Balay 
362e5c89e4eSSatish Balay   err_ind = -1;
363e5c89e4eSSatish Balay   for (j = 0; error_codes[j].code_no; j++) {
364e5c89e4eSSatish Balay     if (error_codes[j].code_no == flt_context.trap) err_ind = j;
365e5c89e4eSSatish Balay   }
366e5c89e4eSSatish Balay 
367a297a907SKarl Rupp   if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name);
368a297a907SKarl Rupp   else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", flt_context.trap);
369a297a907SKarl Rupp 
37049c86fc7SBarry Smith   (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
37141e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
372e5c89e4eSSatish Balay }
373e5c89e4eSSatish Balay 
374*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
375*d71ae5a4SJacob Faibussowitsch {
376e5c89e4eSSatish Balay   PetscFunctionBegin;
377bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
378e5c89e4eSSatish Balay     signal(SIGFPE, (void (*)(int))PetscDefaultFPTrap);
379e5c89e4eSSatish Balay     fp_trap(FP_TRAP_SYNC);
380bd2b07b1SBarry Smith     /* fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); */
381bd2b07b1SBarry Smith     fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
382e5c89e4eSSatish Balay   } else {
383e5c89e4eSSatish Balay     signal(SIGFPE, SIG_DFL);
384cc9df77eSBarry Smith     fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW);
385e5c89e4eSSatish Balay     fp_trap(FP_TRAP_OFF);
386e5c89e4eSSatish Balay   }
387cf0818bdSBarry Smith   _trapmode = flag;
388bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_RS6000_STYLE_FPTRAP\n"));
389e5c89e4eSSatish Balay   PetscFunctionReturn(0);
390e5c89e4eSSatish Balay }
391e5c89e4eSSatish Balay 
392*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
393*d71ae5a4SJacob Faibussowitsch {
394cc9df77eSBarry Smith   PetscFunctionBegin;
3959566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
396cc9df77eSBarry Smith   PetscFunctionReturn(0);
397cc9df77eSBarry Smith }
398cc9df77eSBarry Smith 
399cc9df77eSBarry Smith /* ------------------------------------------------------------*/
400cc9df77eSBarry Smith #elif defined(PETSC_HAVE_WINDOWS_COMPILERS)
401cc9df77eSBarry Smith   #include <float.h>
402*d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
403*d71ae5a4SJacob Faibussowitsch {
404cc9df77eSBarry Smith   PetscFunctionBegin;
405cc9df77eSBarry Smith   (*PetscErrorPrintf)("*** floating point error occurred ***\n");
40649c86fc7SBarry Smith   PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
407cc9df77eSBarry Smith   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
408cc9df77eSBarry Smith }
409cc9df77eSBarry Smith 
410*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
411*d71ae5a4SJacob Faibussowitsch {
412cc9df77eSBarry Smith   unsigned int cw;
413cc9df77eSBarry Smith 
414cc9df77eSBarry Smith   PetscFunctionBegin;
415bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
416bd2b07b1SBarry Smith     /* cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW; */
417bd2b07b1SBarry Smith     cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW;
41808401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
419cc9df77eSBarry Smith   } else {
420cc9df77eSBarry Smith     cw = 0;
42108401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
422cc9df77eSBarry Smith   }
423cc9df77eSBarry Smith   (void)_controlfp(0, cw);
424cf0818bdSBarry Smith   _trapmode = flag;
425bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_WINDOWS_COMPILERS FPTRAP\n"));
426cc9df77eSBarry Smith   PetscFunctionReturn(0);
427cc9df77eSBarry Smith }
428cc9df77eSBarry Smith 
429*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
430*d71ae5a4SJacob Faibussowitsch {
431cc9df77eSBarry Smith   PetscFunctionBegin;
4329566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
433cc9df77eSBarry Smith   PetscFunctionReturn(0);
434cc9df77eSBarry Smith }
435cc9df77eSBarry Smith 
436cc9df77eSBarry Smith /* ------------------------------------------------------------*/
4379a2402e9SBarry Smith #elif defined(PETSC_HAVE_FENV_H) && !defined(__cplusplus)
438b014e56cSJed Brown   /*
439b014e56cSJed Brown    C99 style floating point environment.
440b014e56cSJed Brown 
441b014e56cSJed Brown    Note that C99 merely specifies how to save, restore, and clear the floating
442b014e56cSJed Brown    point environment as well as defining an enumeration of exception codes.  In
443b014e56cSJed Brown    particular, C99 does not specify how to make floating point exceptions raise
444b014e56cSJed Brown    a signal.  Glibc offers this capability through FE_NOMASK_ENV (or with finer
445b014e56cSJed Brown    granularity, feenableexcept()), xmmintrin.h offers _MM_SET_EXCEPTION_MASK().
446b014e56cSJed Brown */
447b014e56cSJed Brown   #include <fenv.h>
4489371c9d4SSatish Balay typedef struct {
4499371c9d4SSatish Balay   int         code;
4509371c9d4SSatish Balay   const char *name;
4519371c9d4SSatish Balay } FPNode;
452b014e56cSJed Brown static const FPNode error_codes[] = {
453b014e56cSJed Brown   {FE_DIVBYZERO, "divide by zero"                                 },
454b014e56cSJed Brown   {FE_INEXACT,   "inexact floating point result"                  },
455b014e56cSJed Brown   {FE_INVALID,   "invalid floating point arguments (domain error)"},
456b014e56cSJed Brown   {FE_OVERFLOW,  "floating point overflow"                        },
457b014e56cSJed Brown   {FE_UNDERFLOW, "floating point underflow"                       },
458b014e56cSJed Brown   {0,            "unknown error"                                  }
459b014e56cSJed Brown };
46099e0435eSBarry Smith 
461*d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
462*d71ae5a4SJacob Faibussowitsch {
463b014e56cSJed Brown   const FPNode *node;
464b014e56cSJed Brown   int           code;
465ace3abfcSBarry Smith   PetscBool     matched = PETSC_FALSE;
466b014e56cSJed Brown 
467b014e56cSJed Brown   PetscFunctionBegin;
468b014e56cSJed Brown   /* Note: While it is possible for the exception state to be preserved by the
469b014e56cSJed Brown    * kernel, this seems to be rare which makes the following flag testing almost
470b014e56cSJed Brown    * useless.  But on a system where the flags can be preserved, it would provide
4717d125cddSJed Brown    * more detail.
472b014e56cSJed Brown    */
473b014e56cSJed Brown   code = fetestexcept(FE_ALL_EXCEPT);
474b014e56cSJed Brown   for (node = &error_codes[0]; node->code; node++) {
475b014e56cSJed Brown     if (code & node->code) {
476b014e56cSJed Brown       matched = PETSC_TRUE;
477b014e56cSJed Brown       (*PetscErrorPrintf)("*** floating point error \"%s\" occurred ***\n", node->name);
478b014e56cSJed Brown       code &= ~node->code; /* Unset this flag since it has been processed */
479b014e56cSJed Brown     }
480b014e56cSJed Brown   }
481b014e56cSJed Brown   if (!matched || code) { /* If any remaining flags are set, or we didn't process any flags */
482b014e56cSJed Brown     (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n");
4837d125cddSJed Brown     (*PetscErrorPrintf)("The specific exception can be determined by running in a debugger.  When the\n");
4847d125cddSJed Brown     (*PetscErrorPrintf)("debugger traps the signal, the exception can be found with fetestexcept(0x%x)\n", FE_ALL_EXCEPT);
4857d125cddSJed Brown     (*PetscErrorPrintf)("where the result is a bitwise OR of the following flags:\n");
4867d125cddSJed 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);
487b014e56cSJed Brown   }
4887d125cddSJed Brown 
4897d125cddSJed Brown   (*PetscErrorPrintf)("Try option -start_in_debugger\n");
49027104ee2SJacob Faibussowitsch   #if PetscDefined(USE_DEBUG)
4917d125cddSJed Brown   (*PetscErrorPrintf)("likely location of problem given in stack below\n");
4927d125cddSJed Brown   (*PetscErrorPrintf)("---------------------  Stack Frames ------------------------------------\n");
493639ff905SBarry Smith   PetscStackView(PETSC_STDOUT);
49427104ee2SJacob Faibussowitsch   #else
4957d125cddSJed Brown   (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
4967d125cddSJed Brown   (*PetscErrorPrintf)("with -start_in_debugger to get more information on the crash.\n");
49727104ee2SJacob Faibussowitsch   #endif
49849c86fc7SBarry Smith   PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_INITIAL, "trapped floating point error");
49941e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
500b014e56cSJed Brown }
501b014e56cSJed Brown 
502*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
503*d71ae5a4SJacob Faibussowitsch {
504b014e56cSJed Brown   PetscFunctionBegin;
505bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
506b014e56cSJed Brown     /* Clear any flags that are currently set so that activating trapping will not immediately call the signal handler. */
507cc73adaaSBarry Smith     PetscCheck(!feclearexcept(FE_ALL_EXCEPT), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot clear floating point exception flags");
508cc9df77eSBarry Smith   #if defined(FE_NOMASK_ENV)
509cc9df77eSBarry Smith     /* Could use fesetenv(FE_NOMASK_ENV), but that causes spurious exceptions (like gettimeofday() -> PetscLogDouble). */
510cf0818bdSBarry Smith     /* PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) != -1,PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot activate floating point exceptions"); */
511bd2b07b1SBarry Smith     /* Doesn't work on AArch64 targets. There's a known hardware limitation. Need to detect hardware at configure time? */
512cf0818bdSBarry Smith     PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW) != -1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot activate floating point exceptions");
513bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with FE_NOMASK_ENV\n"));
514b014e56cSJed Brown   #elif defined PETSC_HAVE_XMMINTRIN_H
515cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_DIV_ZERO);
516bd2b07b1SBarry Smith     /* _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_UNDERFLOW); */
517cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_OVERFLOW);
518cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID);
519bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with PETSC_HAVE_XMMINTRIN_H\n"));
520b014e56cSJed Brown   #else
521b014e56cSJed Brown     /* C99 does not provide a way to modify the environment so there is no portable way to activate trapping. */
522bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP\n"));
523b014e56cSJed Brown   #endif
52408401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
525b014e56cSJed Brown   } else {
526cc73adaaSBarry Smith     PetscCheck(!fesetenv(FE_DFL_ENV), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot disable floating point exceptions");
527cc9df77eSBarry Smith     /* can use _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | _MM_MASK_UNDERFLOW); if PETSC_HAVE_XMMINTRIN_H exists */
52808401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
529b014e56cSJed Brown   }
530cf0818bdSBarry Smith   _trapmode = flag;
531b014e56cSJed Brown   PetscFunctionReturn(0);
532b014e56cSJed Brown }
533b014e56cSJed Brown 
534*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
535*d71ae5a4SJacob Faibussowitsch {
536cc9df77eSBarry Smith   #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
537cc9df77eSBarry Smith   unsigned int flags;
538cc9df77eSBarry Smith   #endif
539cc9df77eSBarry Smith 
540cc9df77eSBarry Smith   PetscFunctionBegin;
541cc9df77eSBarry Smith   #if defined(FE_NOMASK_ENV)
542cc9df77eSBarry Smith   flags = fegetexcept();
543cc9df77eSBarry Smith   if (flags & FE_DIVBYZERO) {
544cc9df77eSBarry Smith   #elif defined PETSC_HAVE_XMMINTRIN_H
545cc9df77eSBarry Smith   flags = _MM_GET_EXCEPTION_MASK();
546cc9df77eSBarry Smith   if (!(flags & _MM_MASK_DIV_ZERO)) {
547cc9df77eSBarry Smith   #else
5489566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Floating point trapping unknown, assuming off\n"));
549cc9df77eSBarry Smith   PetscFunctionReturn(0);
550cc9df77eSBarry Smith   #endif
551cc9df77eSBarry Smith   #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
552cc9df77eSBarry Smith     _trapmode = PETSC_FP_TRAP_ON;
5539566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Floating point trapping is on by default %d\n", flags));
554cc9df77eSBarry Smith   } else {
555cc9df77eSBarry Smith     _trapmode = PETSC_FP_TRAP_OFF;
5569566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Floating point trapping is off by default %d\n", flags));
557cc9df77eSBarry Smith   }
558cc9df77eSBarry Smith   PetscFunctionReturn(0);
559cc9df77eSBarry Smith   #endif
560cc9df77eSBarry Smith }
561cc9df77eSBarry Smith 
562cc9df77eSBarry Smith /* ------------------------------------------------------------*/
563cc9df77eSBarry Smith #elif defined(PETSC_HAVE_IEEEFP_H)
564cc9df77eSBarry Smith   #include <ieeefp.h>
565*d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
566*d71ae5a4SJacob Faibussowitsch {
567cc9df77eSBarry Smith   PetscFunctionBegin;
568cc9df77eSBarry Smith   (*PetscErrorPrintf)("*** floating point error occurred ***\n");
56949c86fc7SBarry Smith   PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
570cc9df77eSBarry Smith   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
571cc9df77eSBarry Smith }
572cc9df77eSBarry Smith 
573*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
574*d71ae5a4SJacob Faibussowitsch {
575cc9df77eSBarry Smith   PetscFunctionBegin;
576cf0818bdSBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
577cc9df77eSBarry Smith   #if defined(PETSC_HAVE_FPPRESETSTICKY)
578cc9df77eSBarry Smith     fpresetsticky(fpgetsticky());
579cc9df77eSBarry Smith   #elif defined(PETSC_HAVE_FPSETSTICKY)
580cc9df77eSBarry Smith     fpsetsticky(fpgetsticky());
581cc9df77eSBarry Smith   #endif
582cc9df77eSBarry Smith     fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_OFL);
58308401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
584cc9df77eSBarry Smith   } else {
585cc9df77eSBarry Smith   #if defined(PETSC_HAVE_FPPRESETSTICKY)
586cc9df77eSBarry Smith     fpresetsticky(fpgetsticky());
587cc9df77eSBarry Smith   #elif defined(PETSC_HAVE_FPSETSTICKY)
588cc9df77eSBarry Smith     fpsetsticky(fpgetsticky());
589cc9df77eSBarry Smith   #endif
590cc9df77eSBarry Smith     fpsetmask(0);
59108401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
592cc9df77eSBarry Smith   }
593cf0818bdSBarry Smith   _trapmode = flag;
594bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IEEEFP_H FPTRAP\n"));
595cc9df77eSBarry Smith   PetscFunctionReturn(0);
596cc9df77eSBarry Smith }
597cc9df77eSBarry Smith 
598*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
599*d71ae5a4SJacob Faibussowitsch {
600cc9df77eSBarry Smith   PetscFunctionBegin;
6019566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
602cc9df77eSBarry Smith   PetscFunctionReturn(0);
603cc9df77eSBarry Smith }
604cc9df77eSBarry Smith 
605e5c89e4eSSatish Balay /* -------------------------Default -----------------------------------*/
606e5c89e4eSSatish Balay #else
60799e0435eSBarry Smith 
608*d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
609*d71ae5a4SJacob Faibussowitsch {
610e5c89e4eSSatish Balay   PetscFunctionBegin;
611e5c89e4eSSatish Balay   (*PetscErrorPrintf)("*** floating point error occurred ***\n");
61249c86fc7SBarry Smith   PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
61341e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
614e5c89e4eSSatish Balay }
61599e0435eSBarry Smith 
616*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
617*d71ae5a4SJacob Faibussowitsch {
618e5c89e4eSSatish Balay   PetscFunctionBegin;
619bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
620a297a907SKarl Rupp     if (SIG_ERR == signal(SIGFPE, PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
621a297a907SKarl Rupp   } else if (SIG_ERR == signal(SIGFPE, SIG_DFL)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
622a297a907SKarl Rupp 
623cf0818bdSBarry Smith   _trapmode = flag;
624bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using default FPTRAP\n"));
625e5c89e4eSSatish Balay   PetscFunctionReturn(0);
626e5c89e4eSSatish Balay }
627cc9df77eSBarry Smith 
628*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
629*d71ae5a4SJacob Faibussowitsch {
630cc9df77eSBarry Smith   PetscFunctionBegin;
6319566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
632cc9df77eSBarry Smith   PetscFunctionReturn(0);
633cc9df77eSBarry Smith }
634e5c89e4eSSatish Balay #endif
635