xref: /petsc/src/sys/error/fp.c (revision fb56d528f54f07f774948260414387da642856bd)
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>
20*fb56d528SJed Brown #if defined(PETSC_HAVE_XMMINTRIN_H)
21*fb56d528SJed Brown   #include <xmmintrin.h>
22*fb56d528SJed Brown #endif
23e5c89e4eSSatish Balay 
24670f3ff9SJed Brown struct PetscFPTrapLink {
25670f3ff9SJed Brown   PetscFPTrap             trapmode;
26670f3ff9SJed Brown   struct PetscFPTrapLink *next;
27670f3ff9SJed Brown };
28aba4c478SBarry Smith static PetscFPTrap             _trapmode = PETSC_FP_TRAP_OFF; /* Current trapping mode; see PetscDetermineInitialFPTrap() */
29670f3ff9SJed Brown static struct PetscFPTrapLink *_trapstack;                    /* Any pushed states of _trapmode */
30670f3ff9SJed Brown 
31670f3ff9SJed Brown /*@
32811af0c4SBarry Smith    PetscFPTrapPush - push a floating point trapping mode, restored using `PetscFPTrapPop()`
33670f3ff9SJed Brown 
34670f3ff9SJed Brown    Not Collective
35670f3ff9SJed Brown 
364165533cSJose E. Roman    Input Parameter:
37811af0c4SBarry Smith .    trap - `PETSC_FP_TRAP_ON` or `PETSC_FP_TRAP_OFF` or any of the values passable to `PetscSetFPTrap()`
38670f3ff9SJed Brown 
39670f3ff9SJed Brown    Level: advanced
40670f3ff9SJed Brown 
41cc9df77eSBarry Smith    Notes:
42cc9df77eSBarry Smith      This only changes the trapping if the new mode is different than the current mode.
43cc9df77eSBarry Smith 
44cc9df77eSBarry Smith      This routine is called to turn off trapping for certain LAPACK routines that assume that dividing
45cc9df77eSBarry Smith      by zero is acceptable. In particular the routine ieeeck().
46cc9df77eSBarry Smith 
47cc9df77eSBarry Smith      Most systems by default have all trapping turned off, but certain Fortran compilers have
48cc9df77eSBarry Smith      link flags that turn on trapping before the program begins.
497de69702SBarry Smith .vb
507de69702SBarry Smith        gfortran -ffpe-trap=invalid,zero,overflow,underflow,denormal
517de69702SBarry Smith        ifort -fpe0
527de69702SBarry Smith .ve
53cc9df77eSBarry Smith 
54db781477SPatrick Sanan .seealso: `PetscFPTrapPop()`, `PetscSetFPTrap()`, `PetscDetermineInitialFPTrap()`
55670f3ff9SJed Brown @*/
56d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPTrapPush(PetscFPTrap trap)
57d71ae5a4SJacob Faibussowitsch {
58670f3ff9SJed Brown   struct PetscFPTrapLink *link;
59670f3ff9SJed Brown 
60670f3ff9SJed Brown   PetscFunctionBegin;
619566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
621f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP)
63ed6c4ed2SJacob Faibussowitsch   PetscPragmaOMP(critical)
641f006be4SPierre Jolivet #endif
651f006be4SPierre Jolivet   {
66670f3ff9SJed Brown     link->trapmode = _trapmode;
67670f3ff9SJed Brown     link->next     = _trapstack;
68670f3ff9SJed Brown     _trapstack     = link;
691f006be4SPierre Jolivet   }
709566063dSJacob Faibussowitsch   if (trap != _trapmode) PetscCall(PetscSetFPTrap(trap));
713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
72670f3ff9SJed Brown }
73670f3ff9SJed Brown 
74670f3ff9SJed Brown /*@
75811af0c4SBarry Smith    PetscFPTrapPop - push a floating point trapping mode, to be restored using `PetscFPTrapPop()`
76670f3ff9SJed Brown 
77670f3ff9SJed Brown    Not Collective
78670f3ff9SJed Brown 
79670f3ff9SJed Brown    Level: advanced
80670f3ff9SJed Brown 
81db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscSetFPTrap()`, `PetscDetermineInitialFPTrap()`
82670f3ff9SJed Brown @*/
83d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPTrapPop(void)
84d71ae5a4SJacob Faibussowitsch {
85670f3ff9SJed Brown   struct PetscFPTrapLink *link;
86670f3ff9SJed Brown 
87670f3ff9SJed Brown   PetscFunctionBegin;
889566063dSJacob Faibussowitsch   if (_trapstack->trapmode != _trapmode) PetscCall(PetscSetFPTrap(_trapstack->trapmode));
891f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP)
90ed6c4ed2SJacob Faibussowitsch   PetscPragmaOMP(critical)
911f006be4SPierre Jolivet #endif
921f006be4SPierre Jolivet   {
93670f3ff9SJed Brown     link       = _trapstack;
94670f3ff9SJed Brown     _trapstack = _trapstack->next;
951f006be4SPierre Jolivet   }
969566063dSJacob Faibussowitsch   PetscCall(PetscFree(link));
973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98670f3ff9SJed Brown }
99670f3ff9SJed Brown 
100e5c89e4eSSatish Balay /*--------------------------------------- ---------------------------------------------------*/
101e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP)
102e5c89e4eSSatish Balay   #include <floatingpoint.h>
103e5c89e4eSSatish Balay 
1048cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_flags(char *, char *, char *, char **);
1058cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_handler(char *, char *, sigfpe_handler_type(int, int, struct sigcontext *, char *));
106e5c89e4eSSatish Balay 
1079371c9d4SSatish Balay static struct {
1089371c9d4SSatish Balay   int   code_no;
1099371c9d4SSatish Balay   char *name;
1109371c9d4SSatish Balay } error_codes[] = {
111e5c89e4eSSatish Balay   {FPE_INTDIV_TRAP,   "integer divide"               },
112e5c89e4eSSatish Balay   {FPE_FLTOPERR_TRAP, "IEEE operand error"           },
113e5c89e4eSSatish Balay   {FPE_FLTOVF_TRAP,   "floating point overflow"      },
114e5c89e4eSSatish Balay   {FPE_FLTUND_TRAP,   "floating point underflow"     },
115e5c89e4eSSatish Balay   {FPE_FLTDIV_TRAP,   "floating pointing divide"     },
116e5c89e4eSSatish Balay   {FPE_FLTINEX_TRAP,  "inexact floating point result"},
117e5c89e4eSSatish Balay   {0,                 "unknown error"                }
118e5c89e4eSSatish Balay };
119e5c89e4eSSatish Balay   #define SIGPC(scp) (scp->sc_pc)
120e5c89e4eSSatish Balay 
121cf0818bdSBarry Smith /* this function gets called if a trap has occurred and been caught */
122d71ae5a4SJacob Faibussowitsch sigfpe_handler_type PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp, char *addr)
123d71ae5a4SJacob Faibussowitsch {
1245f80ce2aSJacob Faibussowitsch   int            err_ind = -1;
1253ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
126e5c89e4eSSatish Balay 
127e5c89e4eSSatish Balay   PetscFunctionBegin;
1285f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
129e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
130e5c89e4eSSatish Balay   }
131e5c89e4eSSatish Balay 
1323ba16761SJacob Faibussowitsch   if (err_ind >= 0) ierr = (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp));
1333ba16761SJacob Faibussowitsch   else ierr = (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp));
134a297a907SKarl Rupp 
1353ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, PETSC_ERR_FP, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
1363ba16761SJacob Faibussowitsch   (void)ierr;
13741e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
1383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
139e5c89e4eSSatish Balay }
140e5c89e4eSSatish Balay 
141e30d2299SSatish Balay /*@
142cf0818bdSBarry Smith    PetscSetFPTrap - Enables traps/exceptions on common floating point errors. This option may not work on certain systems or only a
143cf0818bdSBarry Smith    subset of exceptions may be trapable.
144e5c89e4eSSatish Balay 
145e5c89e4eSSatish Balay    Not Collective
146e5c89e4eSSatish Balay 
1472fe279fdSBarry Smith    Input Parameter:
148cf0818bdSBarry Smith .  flag - values are
149cf0818bdSBarry Smith .vb
150cf0818bdSBarry Smith     PETSC_FP_TRAP_OFF   - do not trap any exceptions
151cf0818bdSBarry Smith     PETSC_FP_TRAP_ON - all exceptions that are possible on the system except underflow
152cf0818bdSBarry Smith     PETSC_FP_TRAP_INDIV - integer divide by zero
153cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTOPERR - improper argument to function, for example with real numbers, the square root of a negative number
154cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTOVF - overflow
155cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTUND - underflow - not trapped by default on most systems
156cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTDIV - floating point divide by zero
157cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTINEX - inexact floating point result
158cf0818bdSBarry Smith .ve
159e5c89e4eSSatish Balay 
1602fe279fdSBarry Smith    Options Database Key:
161cf0818bdSBarry Smith .  -fp_trap <off,on> - turn on or off trapping of floating point exceptions
162e5c89e4eSSatish Balay 
163e5c89e4eSSatish Balay    Level: advanced
164e5c89e4eSSatish Balay 
165cf0818bdSBarry Smith    Notes:
1667de69702SBarry Smith    Preferred usage is `PetscFPTrapPush()` and `PetscFPTrapPop()` instead of this routine
1677de69702SBarry Smith 
168811af0c4SBarry Smith    Currently only `PETSC_FP_TRAP_OFF` and `PETSC_FP_TRAP_ON` are handled. All others are treated as `PETSC_FP_TRAP_ON`.
169cf0818bdSBarry Smith 
170cf0818bdSBarry Smith    The values are bit values and may be |ed together in the function call
171cf0818bdSBarry Smith 
172cf0818bdSBarry Smith    On systems that support it this routine causes floating point
173cf0818bdSBarry Smith    overflow, divide-by-zero, and invalid-operand (e.g., a NaN), but not underflow, to
174e5c89e4eSSatish Balay    cause a message to be printed and the program to exit.
175e5c89e4eSSatish Balay 
176cc9df77eSBarry Smith    On many common systems, the floating
1777d125cddSJed Brown    point exception state is not preserved from the location where the trap
1787d125cddSJed Brown    occurred through to the signal handler.  In this case, the signal handler
1797d125cddSJed Brown    will just say that an unknown floating point exception occurred and which
1807d125cddSJed Brown    function it occurred in.  If you run with -fp_trap in a debugger, it will
181cc9df77eSBarry Smith    break on the line where the error occurred.  On systems that support C99
182cc9df77eSBarry Smith    floating point exception handling You can check which
1837d125cddSJed Brown    exception occurred using fetestexcept(FE_ALL_EXCEPT).  See fenv.h
1847d125cddSJed Brown    (usually at /usr/include/bits/fenv.h) for the enum values on your system.
1857d125cddSJed Brown 
186db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscFPTrapPop()`, `PetscDetermineInitialFPTrap()`
187e5c89e4eSSatish Balay @*/
188d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
189d71ae5a4SJacob Faibussowitsch {
190e5c89e4eSSatish Balay   char *out;
191e5c89e4eSSatish Balay 
192e5c89e4eSSatish Balay   PetscFunctionBegin;
193e5c89e4eSSatish Balay   /* Clear accumulated exceptions.  Used to suppress meaningless messages from f77 programs */
194e5c89e4eSSatish Balay   (void)ieee_flags("clear", "exception", "all", &out);
195bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
196e5c89e4eSSatish Balay     /*
197a297a907SKarl Rupp       To trap more fp exceptions, including underflow, change the line below to
198e5c89e4eSSatish Balay       if (ieee_handler("set","all",PetscDefaultFPTrap)) {
199e5c89e4eSSatish Balay     */
200a297a907SKarl Rupp     if (ieee_handler("set", "common", PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
201a297a907SKarl Rupp   } else if (ieee_handler("clear", "common", PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
202a297a907SKarl Rupp 
203670f3ff9SJed Brown   _trapmode = flag;
204bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_SUN4_STYLE_FPTRAP\n"));
2053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
206e5c89e4eSSatish Balay }
207e5c89e4eSSatish Balay 
208cc9df77eSBarry Smith /*@
209811af0c4SBarry Smith    PetscDetermineInitialFPTrap - Attempts to determine the floating point trapping that exists when `PetscInitialize()` is called
210cc9df77eSBarry Smith 
211cc9df77eSBarry Smith    Not Collective
212cc9df77eSBarry Smith 
213811af0c4SBarry Smith    Note:
214cc9df77eSBarry Smith       Currently only supported on Linux and MacOS. Checks if divide by zero is enable and if so declares that trapping is on.
215cc9df77eSBarry Smith 
216ee300463SSatish Balay    Level: advanced
217cc9df77eSBarry Smith 
218db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscFPTrapPop()`, `PetscDetermineInitialFPTrap()`
219cc9df77eSBarry Smith @*/
220d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
221d71ae5a4SJacob Faibussowitsch {
222cc9df77eSBarry Smith   PetscFunctionBegin;
2239566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
2243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
225cc9df77eSBarry Smith }
226cc9df77eSBarry Smith 
227e5c89e4eSSatish Balay /* -------------------------------------------------------------------------------------------*/
228e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP)
229e5c89e4eSSatish Balay   #include <sunmath.h>
230e5c89e4eSSatish Balay   #include <floatingpoint.h>
231e5c89e4eSSatish Balay   #include <siginfo.h>
232e5c89e4eSSatish Balay   #include <ucontext.h>
233e5c89e4eSSatish Balay 
2349371c9d4SSatish Balay static struct {
2359371c9d4SSatish Balay   int   code_no;
2369371c9d4SSatish Balay   char *name;
2379371c9d4SSatish Balay } error_codes[] = {
238e5c89e4eSSatish Balay   {FPE_FLTINV, "invalid floating point operand"},
239e5c89e4eSSatish Balay   {FPE_FLTRES, "inexact floating point result" },
240e5c89e4eSSatish Balay   {FPE_FLTDIV, "division-by-zero"              },
241e5c89e4eSSatish Balay   {FPE_FLTUND, "floating point underflow"      },
242e5c89e4eSSatish Balay   {FPE_FLTOVF, "floating point overflow"       },
243e5c89e4eSSatish Balay   {0,          "unknown error"                 }
244e5c89e4eSSatish Balay };
245e5c89e4eSSatish Balay   #define SIGPC(scp) (scp->si_addr)
246e5c89e4eSSatish Balay 
247d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig, siginfo_t *scp, ucontext_t *uap)
248d71ae5a4SJacob Faibussowitsch {
2495f80ce2aSJacob Faibussowitsch   int            err_ind = -1, code = scp->si_code;
2503ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
251e5c89e4eSSatish Balay 
252e5c89e4eSSatish Balay   PetscFunctionBegin;
2535f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
254e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
255e5c89e4eSSatish Balay   }
256e5c89e4eSSatish Balay 
2573ba16761SJacob Faibussowitsch   if (err_ind >= 0) ierr = (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp));
2583ba16761SJacob Faibussowitsch   else ierr = (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp));
259a297a907SKarl Rupp 
2603ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
2613ba16761SJacob Faibussowitsch   (void)ierr;
26241e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
263e5c89e4eSSatish Balay }
264e5c89e4eSSatish Balay 
265d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
266d71ae5a4SJacob Faibussowitsch {
267e5c89e4eSSatish Balay   char *out;
268e5c89e4eSSatish Balay 
269e5c89e4eSSatish Balay   PetscFunctionBegin;
270e5c89e4eSSatish Balay   /* Clear accumulated exceptions.  Used to suppress meaningless messages from f77 programs */
271e5c89e4eSSatish Balay   (void)ieee_flags("clear", "exception", "all", &out);
272e5c89e4eSSatish Balay   if (flag == PETSC_FP_TRAP_ON) {
273a297a907SKarl Rupp     if (ieee_handler("set", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n");
274cc9df77eSBarry Smith   } else {
275cc9df77eSBarry Smith     if (ieee_handler("clear", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
276cc9df77eSBarry Smith   }
277670f3ff9SJed Brown   _trapmode = flag;
278bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL,"Using PETSC_HAVE_SOLARIS_STYLE_FPTRAP\n");
2793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
280e5c89e4eSSatish Balay }
281e5c89e4eSSatish Balay 
282d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
283d71ae5a4SJacob Faibussowitsch {
284cc9df77eSBarry Smith   PetscFunctionBegin;
2859566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
2863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
287cc9df77eSBarry Smith }
288cc9df77eSBarry Smith 
289cc9df77eSBarry Smith /* ------------------------------------------------------------------------------------------*/
290e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_IRIX_STYLE_FPTRAP)
291e5c89e4eSSatish Balay   #include <sigfpe.h>
2929371c9d4SSatish Balay static struct {
2939371c9d4SSatish Balay   int   code_no;
2949371c9d4SSatish Balay   char *name;
2959371c9d4SSatish Balay } error_codes[] = {
296e5c89e4eSSatish Balay   {_INVALID, "IEEE operand error"      },
297e5c89e4eSSatish Balay   {_OVERFL,  "floating point overflow" },
298e5c89e4eSSatish Balay   {_UNDERFL, "floating point underflow"},
299e5c89e4eSSatish Balay   {_DIVZERO, "floating point divide"   },
300e5c89e4eSSatish Balay   {0,        "unknown error"           }
301e5c89e4eSSatish Balay };
302d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(unsigned exception[], int val[])
303d71ae5a4SJacob Faibussowitsch {
3045f80ce2aSJacob Faibussowitsch   int            err_ind = -1, code = exception[0];
3053ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
306e5c89e4eSSatish Balay 
307e5c89e4eSSatish Balay   PetscFunctionBegin;
3085f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
309e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
310e5c89e4eSSatish Balay   }
3113ba16761SJacob Faibussowitsch   if (err_ind >= 0) ierr = (*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name);
3123ba16761SJacob Faibussowitsch   else ierr = (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", code);
313a297a907SKarl Rupp 
3143ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
3153ba16761SJacob Faibussowitsch   (void)ierr;
31641e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
317e5c89e4eSSatish Balay }
318e5c89e4eSSatish Balay 
319d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
320d71ae5a4SJacob Faibussowitsch {
321e5c89e4eSSatish Balay   PetscFunctionBegin;
322bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) handle_sigfpes(_ON, , _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, PetscDefaultFPTrap, _ABORT_ON_ERROR, 0);
323cc9df77eSBarry Smith   else handle_sigfpes(_OFF, _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, 0, _ABORT_ON_ERROR, 0);
324670f3ff9SJed Brown   _trapmode = flag;
325bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IRIX_STYLE_FPTRAP\n"));
3263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
327cc9df77eSBarry Smith }
328cc9df77eSBarry Smith 
329d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
330d71ae5a4SJacob Faibussowitsch {
331cc9df77eSBarry Smith   PetscFunctionBegin;
3329566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
3333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
334cc9df77eSBarry Smith }
335cc9df77eSBarry Smith 
336cc9df77eSBarry Smith /*----------------------------------------------- --------------------------------------------*/
337cc9df77eSBarry Smith #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP)
338e5c89e4eSSatish Balay /* In "fast" mode, floating point traps are imprecise and ignored.
339e5c89e4eSSatish Balay    This is the reason for the fptrap(FP_TRAP_SYNC) call */
340e5c89e4eSSatish Balay struct sigcontext;
341e5c89e4eSSatish Balay   #include <fpxcp.h>
342e5c89e4eSSatish Balay   #include <fptrap.h>
343e5c89e4eSSatish Balay   #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000)
344e5c89e4eSSatish Balay   #define FPE_FLTOVF_TRAP   (fptrap_t)(0x10000000)
345e5c89e4eSSatish Balay   #define FPE_FLTUND_TRAP   (fptrap_t)(0x08000000)
346e5c89e4eSSatish Balay   #define FPE_FLTDIV_TRAP   (fptrap_t)(0x04000000)
347e5c89e4eSSatish Balay   #define FPE_FLTINEX_TRAP  (fptrap_t)(0x02000000)
348e5c89e4eSSatish Balay 
3499371c9d4SSatish Balay static struct {
3509371c9d4SSatish Balay   int   code_no;
3519371c9d4SSatish Balay   char *name;
3529371c9d4SSatish Balay } error_codes[] = {
353e5c89e4eSSatish Balay   {FPE_FLTOPERR_TRAP, "IEEE operand error"           },
354e5c89e4eSSatish Balay   {FPE_FLTOVF_TRAP,   "floating point overflow"      },
355e5c89e4eSSatish Balay   {FPE_FLTUND_TRAP,   "floating point underflow"     },
356e5c89e4eSSatish Balay   {FPE_FLTDIV_TRAP,   "floating point divide"        },
357e5c89e4eSSatish Balay   {FPE_FLTINEX_TRAP,  "inexact floating point result"},
358bd2b07b1SBarry Smith   < {0,                 "unknown error"                }
359e5c89e4eSSatish Balay };
360e5c89e4eSSatish Balay   #define SIGPC(scp)        (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */
361e5c89e4eSSatish Balay /*
362e5c89e4eSSatish Balay    For some reason, scp->sc_jmpbuf does not work on the RS6000, even though
363e5c89e4eSSatish Balay    it looks like it should from the include definitions.  It is probably
364e5c89e4eSSatish Balay    some strange interaction with the "POSIX_SOURCE" that we require.
365e5c89e4eSSatish Balay */
366e5c89e4eSSatish Balay 
367d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp)
368d71ae5a4SJacob Faibussowitsch {
369e5c89e4eSSatish Balay   int            err_ind, j;
370e5c89e4eSSatish Balay   fp_ctx_t       flt_context;
3713ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
372e5c89e4eSSatish Balay 
373e5c89e4eSSatish Balay   PetscFunctionBegin;
374e5c89e4eSSatish Balay   fp_sh_trap_info(scp, &flt_context);
375e5c89e4eSSatish Balay 
376e5c89e4eSSatish Balay   err_ind = -1;
377e5c89e4eSSatish Balay   for (j = 0; error_codes[j].code_no; j++) {
378e5c89e4eSSatish Balay     if (error_codes[j].code_no == flt_context.trap) err_ind = j;
379e5c89e4eSSatish Balay   }
380e5c89e4eSSatish Balay 
3813ba16761SJacob Faibussowitsch   if (err_ind >= 0) ierr = (*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name);
3823ba16761SJacob Faibussowitsch   else ierr = (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", flt_context.trap);
383a297a907SKarl Rupp 
3843ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
3853ba16761SJacob Faibussowitsch   (void)ierr;
38641e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
387e5c89e4eSSatish Balay }
388e5c89e4eSSatish Balay 
389d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
390d71ae5a4SJacob Faibussowitsch {
391e5c89e4eSSatish Balay   PetscFunctionBegin;
392bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
393e5c89e4eSSatish Balay     signal(SIGFPE, (void (*)(int))PetscDefaultFPTrap);
394e5c89e4eSSatish Balay     fp_trap(FP_TRAP_SYNC);
395bd2b07b1SBarry Smith     /* fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); */
396bd2b07b1SBarry Smith     fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
397e5c89e4eSSatish Balay   } else {
398e5c89e4eSSatish Balay     signal(SIGFPE, SIG_DFL);
399cc9df77eSBarry Smith     fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW);
400e5c89e4eSSatish Balay     fp_trap(FP_TRAP_OFF);
401e5c89e4eSSatish Balay   }
402cf0818bdSBarry Smith   _trapmode = flag;
403bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_RS6000_STYLE_FPTRAP\n"));
4043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
405e5c89e4eSSatish Balay }
406e5c89e4eSSatish Balay 
407d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
408d71ae5a4SJacob Faibussowitsch {
409cc9df77eSBarry Smith   PetscFunctionBegin;
4109566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
4113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
412cc9df77eSBarry Smith }
413cc9df77eSBarry Smith 
414cc9df77eSBarry Smith /* ------------------------------------------------------------*/
415cc9df77eSBarry Smith #elif defined(PETSC_HAVE_WINDOWS_COMPILERS)
416cc9df77eSBarry Smith   #include <float.h>
417d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
418d71ae5a4SJacob Faibussowitsch {
4193ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
4203ba16761SJacob Faibussowitsch 
421cc9df77eSBarry Smith   PetscFunctionBegin;
4223ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("*** floating point error occurred ***\n");
4233ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
4243ba16761SJacob Faibussowitsch   (void)ierr;
425cc9df77eSBarry Smith   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
426cc9df77eSBarry Smith }
427cc9df77eSBarry Smith 
428d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
429d71ae5a4SJacob Faibussowitsch {
430cc9df77eSBarry Smith   unsigned int cw;
431cc9df77eSBarry Smith 
432cc9df77eSBarry Smith   PetscFunctionBegin;
433bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
434bd2b07b1SBarry Smith     /* cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW; */
435bd2b07b1SBarry Smith     cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW;
43608401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
437cc9df77eSBarry Smith   } else {
438cc9df77eSBarry Smith     cw = 0;
43908401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
440cc9df77eSBarry Smith   }
441cc9df77eSBarry Smith   (void)_controlfp(0, cw);
442cf0818bdSBarry Smith   _trapmode = flag;
443bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_WINDOWS_COMPILERS FPTRAP\n"));
4443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
445cc9df77eSBarry Smith }
446cc9df77eSBarry Smith 
447d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
448d71ae5a4SJacob Faibussowitsch {
449cc9df77eSBarry Smith   PetscFunctionBegin;
4509566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
4513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
452cc9df77eSBarry Smith }
453cc9df77eSBarry Smith 
454cc9df77eSBarry Smith /* ------------------------------------------------------------*/
4559a2402e9SBarry Smith #elif defined(PETSC_HAVE_FENV_H) && !defined(__cplusplus)
456b014e56cSJed Brown   /*
457b014e56cSJed Brown    C99 style floating point environment.
458b014e56cSJed Brown 
459b014e56cSJed Brown    Note that C99 merely specifies how to save, restore, and clear the floating
460b014e56cSJed Brown    point environment as well as defining an enumeration of exception codes.  In
461b014e56cSJed Brown    particular, C99 does not specify how to make floating point exceptions raise
462b014e56cSJed Brown    a signal.  Glibc offers this capability through FE_NOMASK_ENV (or with finer
463b014e56cSJed Brown    granularity, feenableexcept()), xmmintrin.h offers _MM_SET_EXCEPTION_MASK().
464b014e56cSJed Brown */
465b014e56cSJed Brown   #include <fenv.h>
466accbd18bSBarry Smith   #if defined(PETSC_HAVE_FE_VALUES)
4679371c9d4SSatish Balay typedef struct {
4689371c9d4SSatish Balay   int         code;
4699371c9d4SSatish Balay   const char *name;
4709371c9d4SSatish Balay } FPNode;
471b014e56cSJed Brown static const FPNode error_codes[] = {
472b014e56cSJed Brown   {FE_DIVBYZERO, "divide by zero"                                 },
473b014e56cSJed Brown   {FE_INEXACT,   "inexact floating point result"                  },
474b014e56cSJed Brown   {FE_INVALID,   "invalid floating point arguments (domain error)"},
475b014e56cSJed Brown   {FE_OVERFLOW,  "floating point overflow"                        },
476b014e56cSJed Brown   {FE_UNDERFLOW, "floating point underflow"                       },
477b014e56cSJed Brown   {0,            "unknown error"                                  }
478b014e56cSJed Brown };
479accbd18bSBarry Smith   #endif
48099e0435eSBarry Smith 
481d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
482d71ae5a4SJacob Faibussowitsch {
483accbd18bSBarry Smith   #if defined(PETSC_HAVE_FE_VALUES)
484b014e56cSJed Brown   const FPNode  *node;
485b014e56cSJed Brown   int            code;
486ace3abfcSBarry Smith   PetscBool      matched = PETSC_FALSE;
487accbd18bSBarry Smith   #endif
4883ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
489b014e56cSJed Brown 
490b014e56cSJed Brown   PetscFunctionBegin;
491b014e56cSJed Brown   /* Note: While it is possible for the exception state to be preserved by the
492b014e56cSJed Brown    * kernel, this seems to be rare which makes the following flag testing almost
493b014e56cSJed Brown    * useless.  But on a system where the flags can be preserved, it would provide
4947d125cddSJed Brown    * more detail.
495b014e56cSJed Brown    */
496accbd18bSBarry Smith   #if defined(PETSC_HAVE_FE_VALUES)
497b014e56cSJed Brown   code = fetestexcept(FE_ALL_EXCEPT);
498b014e56cSJed Brown   for (node = &error_codes[0]; node->code; node++) {
499b014e56cSJed Brown     if (code & node->code) {
500b014e56cSJed Brown       matched = PETSC_TRUE;
5013ba16761SJacob Faibussowitsch       ierr    = (*PetscErrorPrintf)("*** floating point error \"%s\" occurred ***\n", node->name);
502b014e56cSJed Brown       code &= ~node->code; /* Unset this flag since it has been processed */
503b014e56cSJed Brown     }
504b014e56cSJed Brown   }
505b014e56cSJed Brown   if (!matched || code) { /* If any remaining flags are set, or we didn't process any flags */
5063ba16761SJacob Faibussowitsch     ierr = (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n");
5073ba16761SJacob Faibussowitsch     ierr = (*PetscErrorPrintf)("The specific exception can be determined by running in a debugger.  When the\n");
5083ba16761SJacob Faibussowitsch     ierr = (*PetscErrorPrintf)("debugger traps the signal, the exception can be found with fetestexcept(0x%x)\n", FE_ALL_EXCEPT);
5093ba16761SJacob Faibussowitsch     ierr = (*PetscErrorPrintf)("where the result is a bitwise OR of the following flags:\n");
5103ba16761SJacob Faibussowitsch     ierr = (*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);
511b014e56cSJed Brown   }
512accbd18bSBarry Smith   #else
5133ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n");
514accbd18bSBarry Smith   #endif
5157d125cddSJed Brown 
5163ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("Try option -start_in_debugger\n");
51727104ee2SJacob Faibussowitsch   #if PetscDefined(USE_DEBUG)
518dfb7d7afSStefano Zampini     #if !PetscDefined(HAVE_THREADSAFETY)
5193ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("likely location of problem given in stack below\n");
5203ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("---------------------  Stack Frames ------------------------------------\n");
5213ba16761SJacob Faibussowitsch   ierr = PetscStackView(PETSC_STDOUT);
522dfb7d7afSStefano Zampini     #endif
52327104ee2SJacob Faibussowitsch   #else
5243ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
5253ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("with -start_in_debugger to get more information on the crash.\n");
52627104ee2SJacob Faibussowitsch   #endif
5273ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_INITIAL, "trapped floating point error");
5283ba16761SJacob Faibussowitsch   (void)ierr;
52941e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
530b014e56cSJed Brown }
531b014e56cSJed Brown 
532d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
533d71ae5a4SJacob Faibussowitsch {
534b014e56cSJed Brown   PetscFunctionBegin;
535bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
536b014e56cSJed Brown     /* Clear any flags that are currently set so that activating trapping will not immediately call the signal handler. */
537cc73adaaSBarry Smith     PetscCheck(!feclearexcept(FE_ALL_EXCEPT), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot clear floating point exception flags");
538accbd18bSBarry Smith   #if defined(FE_NOMASK_ENV) && defined(PETSC_HAVE_FE_VALUES)
539cc9df77eSBarry Smith     /* Could use fesetenv(FE_NOMASK_ENV), but that causes spurious exceptions (like gettimeofday() -> PetscLogDouble). */
540cf0818bdSBarry Smith     /* PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) != -1,PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot activate floating point exceptions"); */
541bd2b07b1SBarry Smith     /* Doesn't work on AArch64 targets. There's a known hardware limitation. Need to detect hardware at configure time? */
542cf0818bdSBarry Smith     PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW) != -1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot activate floating point exceptions");
543bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with FE_NOMASK_ENV\n"));
544b014e56cSJed Brown   #elif defined PETSC_HAVE_XMMINTRIN_H
545cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_DIV_ZERO);
546bd2b07b1SBarry Smith     /* _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_UNDERFLOW); */
547cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_OVERFLOW);
548cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID);
549bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with PETSC_HAVE_XMMINTRIN_H\n"));
550b014e56cSJed Brown   #else
551b014e56cSJed Brown     /* C99 does not provide a way to modify the environment so there is no portable way to activate trapping. */
552bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP\n"));
553b014e56cSJed Brown   #endif
55408401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
555b014e56cSJed Brown   } else {
556cc73adaaSBarry Smith     PetscCheck(!fesetenv(FE_DFL_ENV), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot disable floating point exceptions");
557cc9df77eSBarry Smith     /* can use _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | _MM_MASK_UNDERFLOW); if PETSC_HAVE_XMMINTRIN_H exists */
55808401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
559b014e56cSJed Brown   }
560cf0818bdSBarry Smith   _trapmode = flag;
5613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
562b014e56cSJed Brown }
563b014e56cSJed Brown 
564d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
565d71ae5a4SJacob Faibussowitsch {
566cc9df77eSBarry Smith   #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
567cc9df77eSBarry Smith   unsigned int flags;
568cc9df77eSBarry Smith   #endif
569cc9df77eSBarry Smith 
570cc9df77eSBarry Smith   PetscFunctionBegin;
571cc9df77eSBarry Smith   #if defined(FE_NOMASK_ENV)
572cc9df77eSBarry Smith   flags = fegetexcept();
573cc9df77eSBarry Smith   if (flags & FE_DIVBYZERO) {
574cc9df77eSBarry Smith   #elif defined PETSC_HAVE_XMMINTRIN_H
575cc9df77eSBarry Smith   flags = _MM_GET_EXCEPTION_MASK();
576cc9df77eSBarry Smith   if (!(flags & _MM_MASK_DIV_ZERO)) {
577cc9df77eSBarry Smith   #else
5789566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Floating point trapping unknown, assuming off\n"));
5793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
580cc9df77eSBarry Smith   #endif
581cc9df77eSBarry Smith   #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
582cc9df77eSBarry Smith     _trapmode = PETSC_FP_TRAP_ON;
5839566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Floating point trapping is on by default %d\n", flags));
584cc9df77eSBarry Smith   } else {
585cc9df77eSBarry Smith     _trapmode = PETSC_FP_TRAP_OFF;
5869566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Floating point trapping is off by default %d\n", flags));
587cc9df77eSBarry Smith   }
5883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
589cc9df77eSBarry Smith   #endif
590cc9df77eSBarry Smith }
591cc9df77eSBarry Smith 
592cc9df77eSBarry Smith /* ------------------------------------------------------------*/
593cc9df77eSBarry Smith #elif defined(PETSC_HAVE_IEEEFP_H)
594cc9df77eSBarry Smith   #include <ieeefp.h>
595d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
596d71ae5a4SJacob Faibussowitsch {
5973ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
5983ba16761SJacob Faibussowitsch 
599cc9df77eSBarry Smith   PetscFunctionBegin;
6003ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("*** floating point error occurred ***\n");
6013ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
6023ba16761SJacob Faibussowitsch   (void)ierr;
603cc9df77eSBarry Smith   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
604cc9df77eSBarry Smith }
605cc9df77eSBarry Smith 
606d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
607d71ae5a4SJacob Faibussowitsch {
608cc9df77eSBarry Smith   PetscFunctionBegin;
609cf0818bdSBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
61018da0197SPierre Jolivet   #if defined(PETSC_HAVE_FPRESETSTICKY)
611cc9df77eSBarry Smith     fpresetsticky(fpgetsticky());
612cc9df77eSBarry Smith   #elif defined(PETSC_HAVE_FPSETSTICKY)
613cc9df77eSBarry Smith     fpsetsticky(fpgetsticky());
614cc9df77eSBarry Smith   #endif
615cc9df77eSBarry Smith     fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_OFL);
61608401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
617cc9df77eSBarry Smith   } else {
61818da0197SPierre Jolivet   #if defined(PETSC_HAVE_FPRESETSTICKY)
619cc9df77eSBarry Smith     fpresetsticky(fpgetsticky());
620cc9df77eSBarry Smith   #elif defined(PETSC_HAVE_FPSETSTICKY)
621cc9df77eSBarry Smith     fpsetsticky(fpgetsticky());
622cc9df77eSBarry Smith   #endif
623cc9df77eSBarry Smith     fpsetmask(0);
62408401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
625cc9df77eSBarry Smith   }
626cf0818bdSBarry Smith   _trapmode = flag;
627bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IEEEFP_H FPTRAP\n"));
6283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
629cc9df77eSBarry Smith }
630cc9df77eSBarry Smith 
631d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
632d71ae5a4SJacob Faibussowitsch {
633cc9df77eSBarry Smith   PetscFunctionBegin;
6349566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
6353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
636cc9df77eSBarry Smith }
637cc9df77eSBarry Smith 
638e5c89e4eSSatish Balay /* -------------------------Default -----------------------------------*/
639e5c89e4eSSatish Balay #else
64099e0435eSBarry Smith 
641d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
642d71ae5a4SJacob Faibussowitsch {
6433ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
6443ba16761SJacob Faibussowitsch 
645e5c89e4eSSatish Balay   PetscFunctionBegin;
6463ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("*** floating point error occurred ***\n");
6473ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
6483ba16761SJacob Faibussowitsch   (void)ierr;
64941e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
650e5c89e4eSSatish Balay }
65199e0435eSBarry Smith 
652d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
653d71ae5a4SJacob Faibussowitsch {
654e5c89e4eSSatish Balay   PetscFunctionBegin;
655bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
6563ba16761SJacob Faibussowitsch     if (SIG_ERR == signal(SIGFPE, PetscDefaultFPTrap)) PetscCall((*PetscErrorPrintf)("Can't set floatingpoint handler\n"));
6573ba16761SJacob Faibussowitsch   } else if (SIG_ERR == signal(SIGFPE, SIG_DFL)) PetscCall((*PetscErrorPrintf)("Can't clear floatingpoint handler\n"));
658a297a907SKarl Rupp 
659cf0818bdSBarry Smith   _trapmode = flag;
660bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using default FPTRAP\n"));
6613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
662e5c89e4eSSatish Balay }
663cc9df77eSBarry Smith 
664d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
665d71ae5a4SJacob Faibussowitsch {
666cc9df77eSBarry Smith   PetscFunctionBegin;
6679566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
6683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
669cc9df77eSBarry Smith }
670e5c89e4eSSatish Balay #endif
671