xref: /petsc/src/sys/error/fp.c (revision 7de69702b957b5de648b60762d01f4e5276d32ac)
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.
46*7de69702SBarry Smith .vb
47*7de69702SBarry Smith        gfortran -ffpe-trap=invalid,zero,overflow,underflow,denormal
48*7de69702SBarry Smith        ifort -fpe0
49*7de69702SBarry Smith .ve
50cc9df77eSBarry Smith 
51db781477SPatrick Sanan .seealso: `PetscFPTrapPop()`, `PetscSetFPTrap()`, `PetscDetermineInitialFPTrap()`
52670f3ff9SJed Brown @*/
53d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPTrapPush(PetscFPTrap trap)
54d71ae5a4SJacob Faibussowitsch {
55670f3ff9SJed Brown   struct PetscFPTrapLink *link;
56670f3ff9SJed Brown 
57670f3ff9SJed Brown   PetscFunctionBegin;
589566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
591f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP)
60ed6c4ed2SJacob Faibussowitsch   PetscPragmaOMP(critical)
611f006be4SPierre Jolivet #endif
621f006be4SPierre Jolivet   {
63670f3ff9SJed Brown     link->trapmode = _trapmode;
64670f3ff9SJed Brown     link->next     = _trapstack;
65670f3ff9SJed Brown     _trapstack     = link;
661f006be4SPierre Jolivet   }
679566063dSJacob Faibussowitsch   if (trap != _trapmode) PetscCall(PetscSetFPTrap(trap));
683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
69670f3ff9SJed Brown }
70670f3ff9SJed Brown 
71670f3ff9SJed Brown /*@
72811af0c4SBarry Smith    PetscFPTrapPop - push a floating point trapping mode, to be restored using `PetscFPTrapPop()`
73670f3ff9SJed Brown 
74670f3ff9SJed Brown    Not Collective
75670f3ff9SJed Brown 
76670f3ff9SJed Brown    Level: advanced
77670f3ff9SJed Brown 
78db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscSetFPTrap()`, `PetscDetermineInitialFPTrap()`
79670f3ff9SJed Brown @*/
80d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPTrapPop(void)
81d71ae5a4SJacob Faibussowitsch {
82670f3ff9SJed Brown   struct PetscFPTrapLink *link;
83670f3ff9SJed Brown 
84670f3ff9SJed Brown   PetscFunctionBegin;
859566063dSJacob Faibussowitsch   if (_trapstack->trapmode != _trapmode) PetscCall(PetscSetFPTrap(_trapstack->trapmode));
861f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP)
87ed6c4ed2SJacob Faibussowitsch   PetscPragmaOMP(critical)
881f006be4SPierre Jolivet #endif
891f006be4SPierre Jolivet   {
90670f3ff9SJed Brown     link       = _trapstack;
91670f3ff9SJed Brown     _trapstack = _trapstack->next;
921f006be4SPierre Jolivet   }
939566063dSJacob Faibussowitsch   PetscCall(PetscFree(link));
943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95670f3ff9SJed Brown }
96670f3ff9SJed Brown 
97e5c89e4eSSatish Balay /*--------------------------------------- ---------------------------------------------------*/
98e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP)
99e5c89e4eSSatish Balay   #include <floatingpoint.h>
100e5c89e4eSSatish Balay 
1018cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_flags(char *, char *, char *, char **);
1028cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_handler(char *, char *, sigfpe_handler_type(int, int, struct sigcontext *, char *));
103e5c89e4eSSatish Balay 
1049371c9d4SSatish Balay static struct {
1059371c9d4SSatish Balay   int   code_no;
1069371c9d4SSatish Balay   char *name;
1079371c9d4SSatish Balay } error_codes[] = {
108e5c89e4eSSatish Balay   {FPE_INTDIV_TRAP,   "integer divide"               },
109e5c89e4eSSatish Balay   {FPE_FLTOPERR_TRAP, "IEEE operand error"           },
110e5c89e4eSSatish Balay   {FPE_FLTOVF_TRAP,   "floating point overflow"      },
111e5c89e4eSSatish Balay   {FPE_FLTUND_TRAP,   "floating point underflow"     },
112e5c89e4eSSatish Balay   {FPE_FLTDIV_TRAP,   "floating pointing divide"     },
113e5c89e4eSSatish Balay   {FPE_FLTINEX_TRAP,  "inexact floating point result"},
114e5c89e4eSSatish Balay   {0,                 "unknown error"                }
115e5c89e4eSSatish Balay };
116e5c89e4eSSatish Balay   #define SIGPC(scp) (scp->sc_pc)
117e5c89e4eSSatish Balay 
118cf0818bdSBarry Smith /* this function gets called if a trap has occurred and been caught */
119d71ae5a4SJacob Faibussowitsch sigfpe_handler_type PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp, char *addr)
120d71ae5a4SJacob Faibussowitsch {
1215f80ce2aSJacob Faibussowitsch   int            err_ind = -1;
1223ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
123e5c89e4eSSatish Balay 
124e5c89e4eSSatish Balay   PetscFunctionBegin;
1255f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
126e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
127e5c89e4eSSatish Balay   }
128e5c89e4eSSatish Balay 
1293ba16761SJacob Faibussowitsch   if (err_ind >= 0) ierr = (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp));
1303ba16761SJacob Faibussowitsch   else ierr = (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp));
131a297a907SKarl Rupp 
1323ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, PETSC_ERR_FP, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
1333ba16761SJacob Faibussowitsch   (void)ierr;
13441e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
1353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
136e5c89e4eSSatish Balay }
137e5c89e4eSSatish Balay 
138e30d2299SSatish Balay /*@
139cf0818bdSBarry Smith    PetscSetFPTrap - Enables traps/exceptions on common floating point errors. This option may not work on certain systems or only a
140cf0818bdSBarry Smith    subset of exceptions may be trapable.
141e5c89e4eSSatish Balay 
142e5c89e4eSSatish Balay    Not Collective
143e5c89e4eSSatish Balay 
1442fe279fdSBarry Smith    Input Parameter:
145cf0818bdSBarry Smith .  flag - values are
146cf0818bdSBarry Smith .vb
147cf0818bdSBarry Smith     PETSC_FP_TRAP_OFF   - do not trap any exceptions
148cf0818bdSBarry Smith     PETSC_FP_TRAP_ON - all exceptions that are possible on the system except underflow
149cf0818bdSBarry Smith     PETSC_FP_TRAP_INDIV - integer divide by zero
150cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTOPERR - improper argument to function, for example with real numbers, the square root of a negative number
151cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTOVF - overflow
152cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTUND - underflow - not trapped by default on most systems
153cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTDIV - floating point divide by zero
154cf0818bdSBarry Smith     PETSC_FP_TRAP_FLTINEX - inexact floating point result
155cf0818bdSBarry Smith .ve
156e5c89e4eSSatish Balay 
1572fe279fdSBarry Smith    Options Database Key:
158cf0818bdSBarry Smith .  -fp_trap <off,on> - turn on or off trapping of floating point exceptions
159e5c89e4eSSatish Balay 
160e5c89e4eSSatish Balay    Level: advanced
161e5c89e4eSSatish Balay 
162cf0818bdSBarry Smith    Notes:
163*7de69702SBarry Smith    Preferred usage is `PetscFPTrapPush()` and `PetscFPTrapPop()` instead of this routine
164*7de69702SBarry Smith 
165811af0c4SBarry Smith    Currently only `PETSC_FP_TRAP_OFF` and `PETSC_FP_TRAP_ON` are handled. All others are treated as `PETSC_FP_TRAP_ON`.
166cf0818bdSBarry Smith 
167cf0818bdSBarry Smith    The values are bit values and may be |ed together in the function call
168cf0818bdSBarry Smith 
169cf0818bdSBarry Smith    On systems that support it this routine causes floating point
170cf0818bdSBarry Smith    overflow, divide-by-zero, and invalid-operand (e.g., a NaN), but not underflow, to
171e5c89e4eSSatish Balay    cause a message to be printed and the program to exit.
172e5c89e4eSSatish Balay 
173cc9df77eSBarry Smith    On many common systems, the floating
1747d125cddSJed Brown    point exception state is not preserved from the location where the trap
1757d125cddSJed Brown    occurred through to the signal handler.  In this case, the signal handler
1767d125cddSJed Brown    will just say that an unknown floating point exception occurred and which
1777d125cddSJed Brown    function it occurred in.  If you run with -fp_trap in a debugger, it will
178cc9df77eSBarry Smith    break on the line where the error occurred.  On systems that support C99
179cc9df77eSBarry Smith    floating point exception handling You can check which
1807d125cddSJed Brown    exception occurred using fetestexcept(FE_ALL_EXCEPT).  See fenv.h
1817d125cddSJed Brown    (usually at /usr/include/bits/fenv.h) for the enum values on your system.
1827d125cddSJed Brown 
183db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscFPTrapPop()`, `PetscDetermineInitialFPTrap()`
184e5c89e4eSSatish Balay @*/
185d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
186d71ae5a4SJacob Faibussowitsch {
187e5c89e4eSSatish Balay   char *out;
188e5c89e4eSSatish Balay 
189e5c89e4eSSatish Balay   PetscFunctionBegin;
190e5c89e4eSSatish Balay   /* Clear accumulated exceptions.  Used to suppress meaningless messages from f77 programs */
191e5c89e4eSSatish Balay   (void)ieee_flags("clear", "exception", "all", &out);
192bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
193e5c89e4eSSatish Balay     /*
194a297a907SKarl Rupp       To trap more fp exceptions, including underflow, change the line below to
195e5c89e4eSSatish Balay       if (ieee_handler("set","all",PetscDefaultFPTrap)) {
196e5c89e4eSSatish Balay     */
197a297a907SKarl Rupp     if (ieee_handler("set", "common", PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
198a297a907SKarl Rupp   } else if (ieee_handler("clear", "common", PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
199a297a907SKarl Rupp 
200670f3ff9SJed Brown   _trapmode = flag;
201bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_SUN4_STYLE_FPTRAP\n"));
2023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
203e5c89e4eSSatish Balay }
204e5c89e4eSSatish Balay 
205cc9df77eSBarry Smith /*@
206811af0c4SBarry Smith    PetscDetermineInitialFPTrap - Attempts to determine the floating point trapping that exists when `PetscInitialize()` is called
207cc9df77eSBarry Smith 
208cc9df77eSBarry Smith    Not Collective
209cc9df77eSBarry Smith 
210811af0c4SBarry Smith    Note:
211cc9df77eSBarry Smith       Currently only supported on Linux and MacOS. Checks if divide by zero is enable and if so declares that trapping is on.
212cc9df77eSBarry Smith 
213ee300463SSatish Balay    Level: advanced
214cc9df77eSBarry Smith 
215db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscFPTrapPop()`, `PetscDetermineInitialFPTrap()`
216cc9df77eSBarry Smith @*/
217d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
218d71ae5a4SJacob Faibussowitsch {
219cc9df77eSBarry Smith   PetscFunctionBegin;
2209566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
2213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
222cc9df77eSBarry Smith }
223cc9df77eSBarry Smith 
224e5c89e4eSSatish Balay /* -------------------------------------------------------------------------------------------*/
225e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP)
226e5c89e4eSSatish Balay   #include <sunmath.h>
227e5c89e4eSSatish Balay   #include <floatingpoint.h>
228e5c89e4eSSatish Balay   #include <siginfo.h>
229e5c89e4eSSatish Balay   #include <ucontext.h>
230e5c89e4eSSatish Balay 
2319371c9d4SSatish Balay static struct {
2329371c9d4SSatish Balay   int   code_no;
2339371c9d4SSatish Balay   char *name;
2349371c9d4SSatish Balay } error_codes[] = {
235e5c89e4eSSatish Balay   {FPE_FLTINV, "invalid floating point operand"},
236e5c89e4eSSatish Balay   {FPE_FLTRES, "inexact floating point result" },
237e5c89e4eSSatish Balay   {FPE_FLTDIV, "division-by-zero"              },
238e5c89e4eSSatish Balay   {FPE_FLTUND, "floating point underflow"      },
239e5c89e4eSSatish Balay   {FPE_FLTOVF, "floating point overflow"       },
240e5c89e4eSSatish Balay   {0,          "unknown error"                 }
241e5c89e4eSSatish Balay };
242e5c89e4eSSatish Balay   #define SIGPC(scp) (scp->si_addr)
243e5c89e4eSSatish Balay 
244d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig, siginfo_t *scp, ucontext_t *uap)
245d71ae5a4SJacob Faibussowitsch {
2465f80ce2aSJacob Faibussowitsch   int            err_ind = -1, code = scp->si_code;
2473ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
248e5c89e4eSSatish Balay 
249e5c89e4eSSatish Balay   PetscFunctionBegin;
2505f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
251e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
252e5c89e4eSSatish Balay   }
253e5c89e4eSSatish Balay 
2543ba16761SJacob Faibussowitsch   if (err_ind >= 0) ierr = (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp));
2553ba16761SJacob Faibussowitsch   else ierr = (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp));
256a297a907SKarl Rupp 
2573ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
2583ba16761SJacob Faibussowitsch   (void)ierr;
25941e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
260e5c89e4eSSatish Balay }
261e5c89e4eSSatish Balay 
262d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
263d71ae5a4SJacob Faibussowitsch {
264e5c89e4eSSatish Balay   char *out;
265e5c89e4eSSatish Balay 
266e5c89e4eSSatish Balay   PetscFunctionBegin;
267e5c89e4eSSatish Balay   /* Clear accumulated exceptions.  Used to suppress meaningless messages from f77 programs */
268e5c89e4eSSatish Balay   (void)ieee_flags("clear", "exception", "all", &out);
269e5c89e4eSSatish Balay   if (flag == PETSC_FP_TRAP_ON) {
270a297a907SKarl Rupp     if (ieee_handler("set", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n");
271cc9df77eSBarry Smith   } else {
272cc9df77eSBarry Smith     if (ieee_handler("clear", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
273cc9df77eSBarry Smith   }
274670f3ff9SJed Brown   _trapmode = flag;
275bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL,"Using PETSC_HAVE_SOLARIS_STYLE_FPTRAP\n");
2763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
277e5c89e4eSSatish Balay }
278e5c89e4eSSatish Balay 
279d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
280d71ae5a4SJacob Faibussowitsch {
281cc9df77eSBarry Smith   PetscFunctionBegin;
2829566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
2833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
284cc9df77eSBarry Smith }
285cc9df77eSBarry Smith 
286cc9df77eSBarry Smith /* ------------------------------------------------------------------------------------------*/
287e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_IRIX_STYLE_FPTRAP)
288e5c89e4eSSatish Balay   #include <sigfpe.h>
2899371c9d4SSatish Balay static struct {
2909371c9d4SSatish Balay   int   code_no;
2919371c9d4SSatish Balay   char *name;
2929371c9d4SSatish Balay } error_codes[] = {
293e5c89e4eSSatish Balay   {_INVALID, "IEEE operand error"      },
294e5c89e4eSSatish Balay   {_OVERFL,  "floating point overflow" },
295e5c89e4eSSatish Balay   {_UNDERFL, "floating point underflow"},
296e5c89e4eSSatish Balay   {_DIVZERO, "floating point divide"   },
297e5c89e4eSSatish Balay   {0,        "unknown error"           }
298e5c89e4eSSatish Balay };
299d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(unsigned exception[], int val[])
300d71ae5a4SJacob Faibussowitsch {
3015f80ce2aSJacob Faibussowitsch   int            err_ind = -1, code = exception[0];
3023ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
303e5c89e4eSSatish Balay 
304e5c89e4eSSatish Balay   PetscFunctionBegin;
3055f80ce2aSJacob Faibussowitsch   for (int j = 0; error_codes[j].code_no; j++) {
306e5c89e4eSSatish Balay     if (error_codes[j].code_no == code) err_ind = j;
307e5c89e4eSSatish Balay   }
3083ba16761SJacob Faibussowitsch   if (err_ind >= 0) ierr = (*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name);
3093ba16761SJacob Faibussowitsch   else ierr = (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", code);
310a297a907SKarl Rupp 
3113ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
3123ba16761SJacob Faibussowitsch   (void)ierr;
31341e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
314e5c89e4eSSatish Balay }
315e5c89e4eSSatish Balay 
316d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
317d71ae5a4SJacob Faibussowitsch {
318e5c89e4eSSatish Balay   PetscFunctionBegin;
319bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) handle_sigfpes(_ON, , _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, PetscDefaultFPTrap, _ABORT_ON_ERROR, 0);
320cc9df77eSBarry Smith   else handle_sigfpes(_OFF, _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, 0, _ABORT_ON_ERROR, 0);
321670f3ff9SJed Brown   _trapmode = flag;
322bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IRIX_STYLE_FPTRAP\n"));
3233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
324cc9df77eSBarry Smith }
325cc9df77eSBarry Smith 
326d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
327d71ae5a4SJacob Faibussowitsch {
328cc9df77eSBarry Smith   PetscFunctionBegin;
3299566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
3303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
331cc9df77eSBarry Smith }
332cc9df77eSBarry Smith 
333cc9df77eSBarry Smith /*----------------------------------------------- --------------------------------------------*/
334cc9df77eSBarry Smith #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP)
335e5c89e4eSSatish Balay /* In "fast" mode, floating point traps are imprecise and ignored.
336e5c89e4eSSatish Balay    This is the reason for the fptrap(FP_TRAP_SYNC) call */
337e5c89e4eSSatish Balay struct sigcontext;
338e5c89e4eSSatish Balay   #include <fpxcp.h>
339e5c89e4eSSatish Balay   #include <fptrap.h>
340e5c89e4eSSatish Balay   #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000)
341e5c89e4eSSatish Balay   #define FPE_FLTOVF_TRAP   (fptrap_t)(0x10000000)
342e5c89e4eSSatish Balay   #define FPE_FLTUND_TRAP   (fptrap_t)(0x08000000)
343e5c89e4eSSatish Balay   #define FPE_FLTDIV_TRAP   (fptrap_t)(0x04000000)
344e5c89e4eSSatish Balay   #define FPE_FLTINEX_TRAP  (fptrap_t)(0x02000000)
345e5c89e4eSSatish Balay 
3469371c9d4SSatish Balay static struct {
3479371c9d4SSatish Balay   int   code_no;
3489371c9d4SSatish Balay   char *name;
3499371c9d4SSatish Balay } error_codes[] = {
350e5c89e4eSSatish Balay   {FPE_FLTOPERR_TRAP, "IEEE operand error"           },
351e5c89e4eSSatish Balay   {FPE_FLTOVF_TRAP,   "floating point overflow"      },
352e5c89e4eSSatish Balay   {FPE_FLTUND_TRAP,   "floating point underflow"     },
353e5c89e4eSSatish Balay   {FPE_FLTDIV_TRAP,   "floating point divide"        },
354e5c89e4eSSatish Balay   {FPE_FLTINEX_TRAP,  "inexact floating point result"},
355bd2b07b1SBarry Smith   < {0,                 "unknown error"                }
356e5c89e4eSSatish Balay };
357e5c89e4eSSatish Balay   #define SIGPC(scp)        (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */
358e5c89e4eSSatish Balay /*
359e5c89e4eSSatish Balay    For some reason, scp->sc_jmpbuf does not work on the RS6000, even though
360e5c89e4eSSatish Balay    it looks like it should from the include definitions.  It is probably
361e5c89e4eSSatish Balay    some strange interaction with the "POSIX_SOURCE" that we require.
362e5c89e4eSSatish Balay */
363e5c89e4eSSatish Balay 
364d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp)
365d71ae5a4SJacob Faibussowitsch {
366e5c89e4eSSatish Balay   int            err_ind, j;
367e5c89e4eSSatish Balay   fp_ctx_t       flt_context;
3683ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
369e5c89e4eSSatish Balay 
370e5c89e4eSSatish Balay   PetscFunctionBegin;
371e5c89e4eSSatish Balay   fp_sh_trap_info(scp, &flt_context);
372e5c89e4eSSatish Balay 
373e5c89e4eSSatish Balay   err_ind = -1;
374e5c89e4eSSatish Balay   for (j = 0; error_codes[j].code_no; j++) {
375e5c89e4eSSatish Balay     if (error_codes[j].code_no == flt_context.trap) err_ind = j;
376e5c89e4eSSatish Balay   }
377e5c89e4eSSatish Balay 
3783ba16761SJacob Faibussowitsch   if (err_ind >= 0) ierr = (*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name);
3793ba16761SJacob Faibussowitsch   else ierr = (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", flt_context.trap);
380a297a907SKarl Rupp 
3813ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
3823ba16761SJacob Faibussowitsch   (void)ierr;
38341e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
384e5c89e4eSSatish Balay }
385e5c89e4eSSatish Balay 
386d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
387d71ae5a4SJacob Faibussowitsch {
388e5c89e4eSSatish Balay   PetscFunctionBegin;
389bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
390e5c89e4eSSatish Balay     signal(SIGFPE, (void (*)(int))PetscDefaultFPTrap);
391e5c89e4eSSatish Balay     fp_trap(FP_TRAP_SYNC);
392bd2b07b1SBarry Smith     /* fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); */
393bd2b07b1SBarry Smith     fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
394e5c89e4eSSatish Balay   } else {
395e5c89e4eSSatish Balay     signal(SIGFPE, SIG_DFL);
396cc9df77eSBarry Smith     fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW);
397e5c89e4eSSatish Balay     fp_trap(FP_TRAP_OFF);
398e5c89e4eSSatish Balay   }
399cf0818bdSBarry Smith   _trapmode = flag;
400bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_RS6000_STYLE_FPTRAP\n"));
4013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
402e5c89e4eSSatish Balay }
403e5c89e4eSSatish Balay 
404d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
405d71ae5a4SJacob Faibussowitsch {
406cc9df77eSBarry Smith   PetscFunctionBegin;
4079566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
4083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
409cc9df77eSBarry Smith }
410cc9df77eSBarry Smith 
411cc9df77eSBarry Smith /* ------------------------------------------------------------*/
412cc9df77eSBarry Smith #elif defined(PETSC_HAVE_WINDOWS_COMPILERS)
413cc9df77eSBarry Smith   #include <float.h>
414d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
415d71ae5a4SJacob Faibussowitsch {
4163ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
4173ba16761SJacob Faibussowitsch 
418cc9df77eSBarry Smith   PetscFunctionBegin;
4193ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("*** floating point error occurred ***\n");
4203ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
4213ba16761SJacob Faibussowitsch   (void)ierr;
422cc9df77eSBarry Smith   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
423cc9df77eSBarry Smith }
424cc9df77eSBarry Smith 
425d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
426d71ae5a4SJacob Faibussowitsch {
427cc9df77eSBarry Smith   unsigned int cw;
428cc9df77eSBarry Smith 
429cc9df77eSBarry Smith   PetscFunctionBegin;
430bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
431bd2b07b1SBarry Smith     /* cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW; */
432bd2b07b1SBarry Smith     cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW;
43308401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
434cc9df77eSBarry Smith   } else {
435cc9df77eSBarry Smith     cw = 0;
43608401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
437cc9df77eSBarry Smith   }
438cc9df77eSBarry Smith   (void)_controlfp(0, cw);
439cf0818bdSBarry Smith   _trapmode = flag;
440bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_WINDOWS_COMPILERS FPTRAP\n"));
4413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
442cc9df77eSBarry Smith }
443cc9df77eSBarry Smith 
444d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
445d71ae5a4SJacob Faibussowitsch {
446cc9df77eSBarry Smith   PetscFunctionBegin;
4479566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
4483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
449cc9df77eSBarry Smith }
450cc9df77eSBarry Smith 
451cc9df77eSBarry Smith /* ------------------------------------------------------------*/
4529a2402e9SBarry Smith #elif defined(PETSC_HAVE_FENV_H) && !defined(__cplusplus)
453b014e56cSJed Brown   /*
454b014e56cSJed Brown    C99 style floating point environment.
455b014e56cSJed Brown 
456b014e56cSJed Brown    Note that C99 merely specifies how to save, restore, and clear the floating
457b014e56cSJed Brown    point environment as well as defining an enumeration of exception codes.  In
458b014e56cSJed Brown    particular, C99 does not specify how to make floating point exceptions raise
459b014e56cSJed Brown    a signal.  Glibc offers this capability through FE_NOMASK_ENV (or with finer
460b014e56cSJed Brown    granularity, feenableexcept()), xmmintrin.h offers _MM_SET_EXCEPTION_MASK().
461b014e56cSJed Brown */
462b014e56cSJed Brown   #include <fenv.h>
463accbd18bSBarry Smith   #if defined(PETSC_HAVE_FE_VALUES)
4649371c9d4SSatish Balay typedef struct {
4659371c9d4SSatish Balay   int         code;
4669371c9d4SSatish Balay   const char *name;
4679371c9d4SSatish Balay } FPNode;
468b014e56cSJed Brown static const FPNode error_codes[] = {
469b014e56cSJed Brown   {FE_DIVBYZERO, "divide by zero"                                 },
470b014e56cSJed Brown   {FE_INEXACT,   "inexact floating point result"                  },
471b014e56cSJed Brown   {FE_INVALID,   "invalid floating point arguments (domain error)"},
472b014e56cSJed Brown   {FE_OVERFLOW,  "floating point overflow"                        },
473b014e56cSJed Brown   {FE_UNDERFLOW, "floating point underflow"                       },
474b014e56cSJed Brown   {0,            "unknown error"                                  }
475b014e56cSJed Brown };
476accbd18bSBarry Smith   #endif
47799e0435eSBarry Smith 
478d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
479d71ae5a4SJacob Faibussowitsch {
480accbd18bSBarry Smith   #if defined(PETSC_HAVE_FE_VALUES)
481b014e56cSJed Brown   const FPNode  *node;
482b014e56cSJed Brown   int            code;
483ace3abfcSBarry Smith   PetscBool      matched = PETSC_FALSE;
484accbd18bSBarry Smith   #endif
4853ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
486b014e56cSJed Brown 
487b014e56cSJed Brown   PetscFunctionBegin;
488b014e56cSJed Brown   /* Note: While it is possible for the exception state to be preserved by the
489b014e56cSJed Brown    * kernel, this seems to be rare which makes the following flag testing almost
490b014e56cSJed Brown    * useless.  But on a system where the flags can be preserved, it would provide
4917d125cddSJed Brown    * more detail.
492b014e56cSJed Brown    */
493accbd18bSBarry Smith   #if defined(PETSC_HAVE_FE_VALUES)
494b014e56cSJed Brown   code = fetestexcept(FE_ALL_EXCEPT);
495b014e56cSJed Brown   for (node = &error_codes[0]; node->code; node++) {
496b014e56cSJed Brown     if (code & node->code) {
497b014e56cSJed Brown       matched = PETSC_TRUE;
4983ba16761SJacob Faibussowitsch       ierr    = (*PetscErrorPrintf)("*** floating point error \"%s\" occurred ***\n", node->name);
499b014e56cSJed Brown       code &= ~node->code; /* Unset this flag since it has been processed */
500b014e56cSJed Brown     }
501b014e56cSJed Brown   }
502b014e56cSJed Brown   if (!matched || code) { /* If any remaining flags are set, or we didn't process any flags */
5033ba16761SJacob Faibussowitsch     ierr = (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n");
5043ba16761SJacob Faibussowitsch     ierr = (*PetscErrorPrintf)("The specific exception can be determined by running in a debugger.  When the\n");
5053ba16761SJacob Faibussowitsch     ierr = (*PetscErrorPrintf)("debugger traps the signal, the exception can be found with fetestexcept(0x%x)\n", FE_ALL_EXCEPT);
5063ba16761SJacob Faibussowitsch     ierr = (*PetscErrorPrintf)("where the result is a bitwise OR of the following flags:\n");
5073ba16761SJacob 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);
508b014e56cSJed Brown   }
509accbd18bSBarry Smith   #else
5103ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n");
511accbd18bSBarry Smith   #endif
5127d125cddSJed Brown 
5133ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("Try option -start_in_debugger\n");
51427104ee2SJacob Faibussowitsch   #if PetscDefined(USE_DEBUG)
515dfb7d7afSStefano Zampini     #if !PetscDefined(HAVE_THREADSAFETY)
5163ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("likely location of problem given in stack below\n");
5173ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("---------------------  Stack Frames ------------------------------------\n");
5183ba16761SJacob Faibussowitsch   ierr = PetscStackView(PETSC_STDOUT);
519dfb7d7afSStefano Zampini     #endif
52027104ee2SJacob Faibussowitsch   #else
5213ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
5223ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("with -start_in_debugger to get more information on the crash.\n");
52327104ee2SJacob Faibussowitsch   #endif
5243ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_INITIAL, "trapped floating point error");
5253ba16761SJacob Faibussowitsch   (void)ierr;
52641e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
527b014e56cSJed Brown }
528b014e56cSJed Brown 
529d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
530d71ae5a4SJacob Faibussowitsch {
531b014e56cSJed Brown   PetscFunctionBegin;
532bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
533b014e56cSJed Brown     /* Clear any flags that are currently set so that activating trapping will not immediately call the signal handler. */
534cc73adaaSBarry Smith     PetscCheck(!feclearexcept(FE_ALL_EXCEPT), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot clear floating point exception flags");
535accbd18bSBarry Smith   #if defined(FE_NOMASK_ENV) && defined(PETSC_HAVE_FE_VALUES)
536cc9df77eSBarry Smith     /* Could use fesetenv(FE_NOMASK_ENV), but that causes spurious exceptions (like gettimeofday() -> PetscLogDouble). */
537cf0818bdSBarry Smith     /* PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) != -1,PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot activate floating point exceptions"); */
538bd2b07b1SBarry Smith     /* Doesn't work on AArch64 targets. There's a known hardware limitation. Need to detect hardware at configure time? */
539cf0818bdSBarry Smith     PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW) != -1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot activate floating point exceptions");
540bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with FE_NOMASK_ENV\n"));
541b014e56cSJed Brown   #elif defined PETSC_HAVE_XMMINTRIN_H
542cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_DIV_ZERO);
543bd2b07b1SBarry Smith     /* _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_UNDERFLOW); */
544cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_OVERFLOW);
545cc9df77eSBarry Smith     _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID);
546bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with PETSC_HAVE_XMMINTRIN_H\n"));
547b014e56cSJed Brown   #else
548b014e56cSJed Brown     /* C99 does not provide a way to modify the environment so there is no portable way to activate trapping. */
549bd2b07b1SBarry Smith     PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP\n"));
550b014e56cSJed Brown   #endif
55108401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
552b014e56cSJed Brown   } else {
553cc73adaaSBarry Smith     PetscCheck(!fesetenv(FE_DFL_ENV), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot disable floating point exceptions");
554cc9df77eSBarry Smith     /* can use _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | _MM_MASK_UNDERFLOW); if PETSC_HAVE_XMMINTRIN_H exists */
55508401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
556b014e56cSJed Brown   }
557cf0818bdSBarry Smith   _trapmode = flag;
5583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
559b014e56cSJed Brown }
560b014e56cSJed Brown 
561d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
562d71ae5a4SJacob Faibussowitsch {
563cc9df77eSBarry Smith   #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
564cc9df77eSBarry Smith   unsigned int flags;
565cc9df77eSBarry Smith   #endif
566cc9df77eSBarry Smith 
567cc9df77eSBarry Smith   PetscFunctionBegin;
568cc9df77eSBarry Smith   #if defined(FE_NOMASK_ENV)
569cc9df77eSBarry Smith   flags = fegetexcept();
570cc9df77eSBarry Smith   if (flags & FE_DIVBYZERO) {
571cc9df77eSBarry Smith   #elif defined PETSC_HAVE_XMMINTRIN_H
572cc9df77eSBarry Smith   flags = _MM_GET_EXCEPTION_MASK();
573cc9df77eSBarry Smith   if (!(flags & _MM_MASK_DIV_ZERO)) {
574cc9df77eSBarry Smith   #else
5759566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Floating point trapping unknown, assuming off\n"));
5763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
577cc9df77eSBarry Smith   #endif
578cc9df77eSBarry Smith   #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
579cc9df77eSBarry Smith     _trapmode = PETSC_FP_TRAP_ON;
5809566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Floating point trapping is on by default %d\n", flags));
581cc9df77eSBarry Smith   } else {
582cc9df77eSBarry Smith     _trapmode = PETSC_FP_TRAP_OFF;
5839566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Floating point trapping is off by default %d\n", flags));
584cc9df77eSBarry Smith   }
5853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
586cc9df77eSBarry Smith   #endif
587cc9df77eSBarry Smith }
588cc9df77eSBarry Smith 
589cc9df77eSBarry Smith /* ------------------------------------------------------------*/
590cc9df77eSBarry Smith #elif defined(PETSC_HAVE_IEEEFP_H)
591cc9df77eSBarry Smith   #include <ieeefp.h>
592d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
593d71ae5a4SJacob Faibussowitsch {
5943ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
5953ba16761SJacob Faibussowitsch 
596cc9df77eSBarry Smith   PetscFunctionBegin;
5973ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("*** floating point error occurred ***\n");
5983ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
5993ba16761SJacob Faibussowitsch   (void)ierr;
600cc9df77eSBarry Smith   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
601cc9df77eSBarry Smith }
602cc9df77eSBarry Smith 
603d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
604d71ae5a4SJacob Faibussowitsch {
605cc9df77eSBarry Smith   PetscFunctionBegin;
606cf0818bdSBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
60718da0197SPierre Jolivet   #if defined(PETSC_HAVE_FPRESETSTICKY)
608cc9df77eSBarry Smith     fpresetsticky(fpgetsticky());
609cc9df77eSBarry Smith   #elif defined(PETSC_HAVE_FPSETSTICKY)
610cc9df77eSBarry Smith     fpsetsticky(fpgetsticky());
611cc9df77eSBarry Smith   #endif
612cc9df77eSBarry Smith     fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_OFL);
61308401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
614cc9df77eSBarry Smith   } else {
61518da0197SPierre Jolivet   #if defined(PETSC_HAVE_FPRESETSTICKY)
616cc9df77eSBarry Smith     fpresetsticky(fpgetsticky());
617cc9df77eSBarry Smith   #elif defined(PETSC_HAVE_FPSETSTICKY)
618cc9df77eSBarry Smith     fpsetsticky(fpgetsticky());
619cc9df77eSBarry Smith   #endif
620cc9df77eSBarry Smith     fpsetmask(0);
62108401ef6SPierre Jolivet     PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
622cc9df77eSBarry Smith   }
623cf0818bdSBarry Smith   _trapmode = flag;
624bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IEEEFP_H FPTRAP\n"));
6253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
626cc9df77eSBarry Smith }
627cc9df77eSBarry Smith 
628d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
629d71ae5a4SJacob Faibussowitsch {
630cc9df77eSBarry Smith   PetscFunctionBegin;
6319566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
6323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
633cc9df77eSBarry Smith }
634cc9df77eSBarry Smith 
635e5c89e4eSSatish Balay /* -------------------------Default -----------------------------------*/
636e5c89e4eSSatish Balay #else
63799e0435eSBarry Smith 
638d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
639d71ae5a4SJacob Faibussowitsch {
6403ba16761SJacob Faibussowitsch   PetscErrorCode ierr;
6413ba16761SJacob Faibussowitsch 
642e5c89e4eSSatish Balay   PetscFunctionBegin;
6433ba16761SJacob Faibussowitsch   ierr = (*PetscErrorPrintf)("*** floating point error occurred ***\n");
6443ba16761SJacob Faibussowitsch   ierr = PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
6453ba16761SJacob Faibussowitsch   (void)ierr;
64641e02c4dSJunchao Zhang   PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
647e5c89e4eSSatish Balay }
64899e0435eSBarry Smith 
649d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
650d71ae5a4SJacob Faibussowitsch {
651e5c89e4eSSatish Balay   PetscFunctionBegin;
652bd2b07b1SBarry Smith   if (flag == PETSC_FP_TRAP_ON) {
6533ba16761SJacob Faibussowitsch     if (SIG_ERR == signal(SIGFPE, PetscDefaultFPTrap)) PetscCall((*PetscErrorPrintf)("Can't set floatingpoint handler\n"));
6543ba16761SJacob Faibussowitsch   } else if (SIG_ERR == signal(SIGFPE, SIG_DFL)) PetscCall((*PetscErrorPrintf)("Can't clear floatingpoint handler\n"));
655a297a907SKarl Rupp 
656cf0818bdSBarry Smith   _trapmode = flag;
657bd2b07b1SBarry Smith   PetscCall(PetscInfo(NULL, "Using default FPTRAP\n"));
6583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
659e5c89e4eSSatish Balay }
660cc9df77eSBarry Smith 
661d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
662d71ae5a4SJacob Faibussowitsch {
663cc9df77eSBarry Smith   PetscFunctionBegin;
6649566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
6653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
666cc9df77eSBarry Smith }
667e5c89e4eSSatish Balay #endif
668