1e5c89e4eSSatish Balay /*
20e3d61c9SBarry Smith IEEE error handler for all machines. Since each OS has
30e3d61c9SBarry Smith enough slight differences we have completely separate codes for each one.
4e5c89e4eSSatish Balay */
5b014e56cSJed Brown
6b014e56cSJed Brown /*
7b014e56cSJed Brown This feature test macro provides FE_NOMASK_ENV on GNU. It must be defined
8b014e56cSJed Brown at the top of the file because other headers may pull in fenv.h even when
9b014e56cSJed Brown not strictly necessary. Strictly speaking, we could include ONLY petscconf.h,
10b014e56cSJed Brown check PETSC_HAVE_FENV_H, and only define _GNU_SOURCE in that case, but such
11b014e56cSJed Brown shenanigans ought to be unnecessary.
12b014e56cSJed Brown */
13519f805aSKarl Rupp #if !defined(_GNU_SOURCE)
14b014e56cSJed Brown #define _GNU_SOURCE
1576a6984eSJed Brown #endif
16b014e56cSJed Brown
1727104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
18e5c89e4eSSatish Balay #include <signal.h>
19fb56d528SJed Brown #if defined(PETSC_HAVE_XMMINTRIN_H)
20fb56d528SJed Brown #include <xmmintrin.h>
21fb56d528SJed Brown #endif
22e5c89e4eSSatish Balay
23670f3ff9SJed Brown struct PetscFPTrapLink {
24670f3ff9SJed Brown PetscFPTrap trapmode;
25670f3ff9SJed Brown struct PetscFPTrapLink *next;
26670f3ff9SJed Brown };
27aba4c478SBarry Smith static PetscFPTrap _trapmode = PETSC_FP_TRAP_OFF; /* Current trapping mode; see PetscDetermineInitialFPTrap() */
28670f3ff9SJed Brown static struct PetscFPTrapLink *_trapstack; /* Any pushed states of _trapmode */
29670f3ff9SJed Brown
30670f3ff9SJed Brown /*@
31811af0c4SBarry Smith PetscFPTrapPush - push a floating point trapping mode, restored using `PetscFPTrapPop()`
32670f3ff9SJed Brown
33670f3ff9SJed Brown Not Collective
34670f3ff9SJed Brown
354165533cSJose E. Roman Input Parameter:
36811af0c4SBarry Smith . trap - `PETSC_FP_TRAP_ON` or `PETSC_FP_TRAP_OFF` or any of the values passable to `PetscSetFPTrap()`
37670f3ff9SJed Brown
38670f3ff9SJed Brown Level: advanced
39670f3ff9SJed Brown
40cc9df77eSBarry Smith Notes:
41cc9df77eSBarry Smith This only changes the trapping if the new mode is different than the current mode.
42cc9df77eSBarry Smith
43cc9df77eSBarry Smith This routine is called to turn off trapping for certain LAPACK routines that assume that dividing
44cc9df77eSBarry Smith by zero is acceptable. In particular the routine ieeeck().
45cc9df77eSBarry Smith
46cc9df77eSBarry Smith Most systems by default have all trapping turned off, but certain Fortran compilers have
47cc9df77eSBarry Smith link flags that turn on trapping before the program begins.
487de69702SBarry Smith .vb
497de69702SBarry Smith gfortran -ffpe-trap=invalid,zero,overflow,underflow,denormal
507de69702SBarry Smith ifort -fpe0
517de69702SBarry Smith .ve
52cc9df77eSBarry Smith
53db781477SPatrick Sanan .seealso: `PetscFPTrapPop()`, `PetscSetFPTrap()`, `PetscDetermineInitialFPTrap()`
54670f3ff9SJed Brown @*/
PetscFPTrapPush(PetscFPTrap trap)55d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPTrapPush(PetscFPTrap trap)
56d71ae5a4SJacob Faibussowitsch {
57670f3ff9SJed Brown struct PetscFPTrapLink *link;
58670f3ff9SJed Brown
59670f3ff9SJed Brown PetscFunctionBegin;
609566063dSJacob Faibussowitsch PetscCall(PetscNew(&link));
611f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP)
62ed6c4ed2SJacob Faibussowitsch PetscPragmaOMP(critical)
631f006be4SPierre Jolivet #endif
641f006be4SPierre Jolivet {
65670f3ff9SJed Brown link->trapmode = _trapmode;
66670f3ff9SJed Brown link->next = _trapstack;
67670f3ff9SJed Brown _trapstack = link;
681f006be4SPierre Jolivet }
699566063dSJacob Faibussowitsch if (trap != _trapmode) PetscCall(PetscSetFPTrap(trap));
703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
71670f3ff9SJed Brown }
72670f3ff9SJed Brown
73670f3ff9SJed Brown /*@
74811af0c4SBarry Smith PetscFPTrapPop - push a floating point trapping mode, to be restored using `PetscFPTrapPop()`
75670f3ff9SJed Brown
76670f3ff9SJed Brown Not Collective
77670f3ff9SJed Brown
78670f3ff9SJed Brown Level: advanced
79670f3ff9SJed Brown
80db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscSetFPTrap()`, `PetscDetermineInitialFPTrap()`
81670f3ff9SJed Brown @*/
PetscFPTrapPop(void)82d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPTrapPop(void)
83d71ae5a4SJacob Faibussowitsch {
84670f3ff9SJed Brown struct PetscFPTrapLink *link;
85670f3ff9SJed Brown
86670f3ff9SJed Brown PetscFunctionBegin;
879566063dSJacob Faibussowitsch if (_trapstack->trapmode != _trapmode) PetscCall(PetscSetFPTrap(_trapstack->trapmode));
881f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP)
89ed6c4ed2SJacob Faibussowitsch PetscPragmaOMP(critical)
901f006be4SPierre Jolivet #endif
911f006be4SPierre Jolivet {
92670f3ff9SJed Brown link = _trapstack;
93670f3ff9SJed Brown _trapstack = _trapstack->next;
941f006be4SPierre Jolivet }
959566063dSJacob Faibussowitsch PetscCall(PetscFree(link));
963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
97670f3ff9SJed Brown }
98670f3ff9SJed Brown
99e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP)
100e5c89e4eSSatish Balay #include <floatingpoint.h>
101e5c89e4eSSatish Balay
1028cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_flags(char *, char *, char *, char **);
1038cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_handler(char *, char *, sigfpe_handler_type(int, int, struct sigcontext *, char *));
104e5c89e4eSSatish Balay
1059371c9d4SSatish Balay static struct {
1069371c9d4SSatish Balay int code_no;
1079371c9d4SSatish Balay char *name;
1089371c9d4SSatish Balay } error_codes[] = {
109e5c89e4eSSatish Balay {FPE_INTDIV_TRAP, "integer divide" },
110e5c89e4eSSatish Balay {FPE_FLTOPERR_TRAP, "IEEE operand error" },
111e5c89e4eSSatish Balay {FPE_FLTOVF_TRAP, "floating point overflow" },
112e5c89e4eSSatish Balay {FPE_FLTUND_TRAP, "floating point underflow" },
113e5c89e4eSSatish Balay {FPE_FLTDIV_TRAP, "floating pointing divide" },
114e5c89e4eSSatish Balay {FPE_FLTINEX_TRAP, "inexact floating point result"},
115e5c89e4eSSatish Balay {0, "unknown error" }
116e5c89e4eSSatish Balay };
117e5c89e4eSSatish Balay #define SIGPC(scp) (scp->sc_pc)
118e5c89e4eSSatish Balay
119cf0818bdSBarry Smith /* this function gets called if a trap has occurred and been caught */
PetscDefaultFPTrap(int sig,int code,struct sigcontext * scp,char * addr)120d71ae5a4SJacob Faibussowitsch sigfpe_handler_type PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp, char *addr)
121d71ae5a4SJacob Faibussowitsch {
1225f80ce2aSJacob Faibussowitsch int err_ind = -1;
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
129dd460d27SBarry Smith if (err_ind >= 0) (void)(*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp));
130dd460d27SBarry Smith else (void)(*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp));
131a297a907SKarl Rupp
132dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, PETSC_ERR_FP, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
13341e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
1343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
135e5c89e4eSSatish Balay }
136e5c89e4eSSatish Balay
137e30d2299SSatish Balay /*@
138cf0818bdSBarry Smith PetscSetFPTrap - Enables traps/exceptions on common floating point errors. This option may not work on certain systems or only a
139cf0818bdSBarry Smith subset of exceptions may be trapable.
140e5c89e4eSSatish Balay
141e5c89e4eSSatish Balay Not Collective
142e5c89e4eSSatish Balay
1432fe279fdSBarry Smith Input Parameter:
144cf0818bdSBarry Smith . flag - values are
145cf0818bdSBarry Smith .vb
146cf0818bdSBarry Smith PETSC_FP_TRAP_OFF - do not trap any exceptions
147cf0818bdSBarry Smith PETSC_FP_TRAP_ON - all exceptions that are possible on the system except underflow
148cf0818bdSBarry Smith PETSC_FP_TRAP_INDIV - integer divide by zero
149cf0818bdSBarry Smith PETSC_FP_TRAP_FLTOPERR - improper argument to function, for example with real numbers, the square root of a negative number
150cf0818bdSBarry Smith PETSC_FP_TRAP_FLTOVF - overflow
151cf0818bdSBarry Smith PETSC_FP_TRAP_FLTUND - underflow - not trapped by default on most systems
152cf0818bdSBarry Smith PETSC_FP_TRAP_FLTDIV - floating point divide by zero
153cf0818bdSBarry Smith PETSC_FP_TRAP_FLTINEX - inexact floating point result
154cf0818bdSBarry Smith .ve
155e5c89e4eSSatish Balay
1562fe279fdSBarry Smith Options Database Key:
157cf0818bdSBarry Smith . -fp_trap <off,on> - turn on or off trapping of floating point exceptions
158e5c89e4eSSatish Balay
159e5c89e4eSSatish Balay Level: advanced
160e5c89e4eSSatish Balay
161cf0818bdSBarry Smith Notes:
1627de69702SBarry Smith Preferred usage is `PetscFPTrapPush()` and `PetscFPTrapPop()` instead of this routine
1637de69702SBarry Smith
164811af0c4SBarry Smith Currently only `PETSC_FP_TRAP_OFF` and `PETSC_FP_TRAP_ON` are handled. All others are treated as `PETSC_FP_TRAP_ON`.
165cf0818bdSBarry Smith
166cf0818bdSBarry Smith The values are bit values and may be |ed together in the function call
167cf0818bdSBarry Smith
168cf0818bdSBarry Smith On systems that support it this routine causes floating point
169cf0818bdSBarry Smith overflow, divide-by-zero, and invalid-operand (e.g., a NaN), but not underflow, to
170e5c89e4eSSatish Balay cause a message to be printed and the program to exit.
171e5c89e4eSSatish Balay
172cc9df77eSBarry Smith On many common systems, the floating
1737d125cddSJed Brown point exception state is not preserved from the location where the trap
1747d125cddSJed Brown occurred through to the signal handler. In this case, the signal handler
1757d125cddSJed Brown will just say that an unknown floating point exception occurred and which
1767d125cddSJed Brown function it occurred in. If you run with -fp_trap in a debugger, it will
177cc9df77eSBarry Smith break on the line where the error occurred. On systems that support C99
178cc9df77eSBarry Smith floating point exception handling You can check which
1797d125cddSJed Brown exception occurred using fetestexcept(FE_ALL_EXCEPT). See fenv.h
1807d125cddSJed Brown (usually at /usr/include/bits/fenv.h) for the enum values on your system.
1817d125cddSJed Brown
182db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscFPTrapPop()`, `PetscDetermineInitialFPTrap()`
183e5c89e4eSSatish Balay @*/
PetscSetFPTrap(PetscFPTrap flag)184d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
185d71ae5a4SJacob Faibussowitsch {
186e5c89e4eSSatish Balay char *out;
187e5c89e4eSSatish Balay
188e5c89e4eSSatish Balay PetscFunctionBegin;
189e5c89e4eSSatish Balay /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */
190e5c89e4eSSatish Balay (void)ieee_flags("clear", "exception", "all", &out);
191bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) {
192e5c89e4eSSatish Balay /*
193a297a907SKarl Rupp To trap more fp exceptions, including underflow, change the line below to
194e5c89e4eSSatish Balay if (ieee_handler("set","all",PetscDefaultFPTrap)) {
195e5c89e4eSSatish Balay */
196a297a907SKarl Rupp if (ieee_handler("set", "common", PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
197a297a907SKarl Rupp } else if (ieee_handler("clear", "common", PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
198a297a907SKarl Rupp
199670f3ff9SJed Brown _trapmode = flag;
200bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_SUN4_STYLE_FPTRAP\n"));
2013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
202e5c89e4eSSatish Balay }
203e5c89e4eSSatish Balay
204cc9df77eSBarry Smith /*@
205811af0c4SBarry Smith PetscDetermineInitialFPTrap - Attempts to determine the floating point trapping that exists when `PetscInitialize()` is called
206cc9df77eSBarry Smith
207cc9df77eSBarry Smith Not Collective
208cc9df77eSBarry Smith
209811af0c4SBarry Smith Note:
210337bb527SBarry Smith Currently only supported on Linux and macOS. Checks if divide by zero is enable and if so declares that trapping is on.
211cc9df77eSBarry Smith
212ee300463SSatish Balay Level: advanced
213cc9df77eSBarry Smith
214db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscFPTrapPop()`, `PetscDetermineInitialFPTrap()`
215cc9df77eSBarry Smith @*/
PetscDetermineInitialFPTrap(void)216d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
217d71ae5a4SJacob Faibussowitsch {
218cc9df77eSBarry Smith PetscFunctionBegin;
2199566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
2203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
221cc9df77eSBarry Smith }
222cc9df77eSBarry Smith
223e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP)
224e5c89e4eSSatish Balay #include <sunmath.h>
225e5c89e4eSSatish Balay #include <floatingpoint.h>
226e5c89e4eSSatish Balay #include <siginfo.h>
227e5c89e4eSSatish Balay #include <ucontext.h>
228e5c89e4eSSatish Balay
2299371c9d4SSatish Balay static struct {
2309371c9d4SSatish Balay int code_no;
2319371c9d4SSatish Balay char *name;
2329371c9d4SSatish Balay } error_codes[] = {
233e5c89e4eSSatish Balay {FPE_FLTINV, "invalid floating point operand"},
234e5c89e4eSSatish Balay {FPE_FLTRES, "inexact floating point result" },
235e5c89e4eSSatish Balay {FPE_FLTDIV, "division-by-zero" },
236e5c89e4eSSatish Balay {FPE_FLTUND, "floating point underflow" },
237e5c89e4eSSatish Balay {FPE_FLTOVF, "floating point overflow" },
238e5c89e4eSSatish Balay {0, "unknown error" }
239e5c89e4eSSatish Balay };
240e5c89e4eSSatish Balay #define SIGPC(scp) (scp->si_addr)
241e5c89e4eSSatish Balay
PetscDefaultFPTrap(int sig,siginfo_t * scp,ucontext_t * uap)242d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig, siginfo_t *scp, ucontext_t *uap)
243d71ae5a4SJacob Faibussowitsch {
2445f80ce2aSJacob Faibussowitsch int err_ind = -1, code = scp->si_code;
245e5c89e4eSSatish Balay
246e5c89e4eSSatish Balay PetscFunctionBegin;
2475f80ce2aSJacob Faibussowitsch for (int j = 0; error_codes[j].code_no; j++) {
248e5c89e4eSSatish Balay if (error_codes[j].code_no == code) err_ind = j;
249e5c89e4eSSatish Balay }
250e5c89e4eSSatish Balay
251dd460d27SBarry Smith if (err_ind >= 0) (void)(*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp));
252dd460d27SBarry Smith else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp));
253a297a907SKarl Rupp
254dd460d27SBarry Smith PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
25541e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
256e5c89e4eSSatish Balay }
257e5c89e4eSSatish Balay
PetscSetFPTrap(PetscFPTrap flag)258d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
259d71ae5a4SJacob Faibussowitsch {
260e5c89e4eSSatish Balay char *out;
261e5c89e4eSSatish Balay
262e5c89e4eSSatish Balay PetscFunctionBegin;
263e5c89e4eSSatish Balay /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */
264e5c89e4eSSatish Balay (void)ieee_flags("clear", "exception", "all", &out);
265e5c89e4eSSatish Balay if (flag == PETSC_FP_TRAP_ON) {
266a297a907SKarl Rupp if (ieee_handler("set", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n");
267cc9df77eSBarry Smith } else {
268cc9df77eSBarry Smith if (ieee_handler("clear", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
269cc9df77eSBarry Smith }
270670f3ff9SJed Brown _trapmode = flag;
271bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL,"Using PETSC_HAVE_SOLARIS_STYLE_FPTRAP\n");
2723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
273e5c89e4eSSatish Balay }
274e5c89e4eSSatish Balay
275d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
276d71ae5a4SJacob Faibussowitsch {
277cc9df77eSBarry Smith PetscFunctionBegin;
2789566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
2793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
280cc9df77eSBarry Smith }
281cc9df77eSBarry Smith
282e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_IRIX_STYLE_FPTRAP)
283e5c89e4eSSatish Balay #include <sigfpe.h>
2849371c9d4SSatish Balay static struct {
2859371c9d4SSatish Balay int code_no;
2869371c9d4SSatish Balay char *name;
2879371c9d4SSatish Balay } error_codes[] = {
288e5c89e4eSSatish Balay {_INVALID, "IEEE operand error" },
289e5c89e4eSSatish Balay {_OVERFL, "floating point overflow" },
290e5c89e4eSSatish Balay {_UNDERFL, "floating point underflow"},
291e5c89e4eSSatish Balay {_DIVZERO, "floating point divide" },
292e5c89e4eSSatish Balay {0, "unknown error" }
293e5c89e4eSSatish Balay };
294d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(unsigned exception[], int val[])
295d71ae5a4SJacob Faibussowitsch {
2965f80ce2aSJacob Faibussowitsch int err_ind = -1, code = exception[0];
297e5c89e4eSSatish Balay
298e5c89e4eSSatish Balay PetscFunctionBegin;
2995f80ce2aSJacob Faibussowitsch for (int j = 0; error_codes[j].code_no; j++) {
300e5c89e4eSSatish Balay if (error_codes[j].code_no == code) err_ind = j;
301e5c89e4eSSatish Balay }
302dd460d27SBarry Smith if (err_ind >= 0) (void)(*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name);
303dd460d27SBarry Smith else (void)(*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", code);
304a297a907SKarl Rupp
305dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
30641e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
307e5c89e4eSSatish Balay }
308e5c89e4eSSatish Balay
309d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
310d71ae5a4SJacob Faibussowitsch {
311e5c89e4eSSatish Balay PetscFunctionBegin;
312bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) handle_sigfpes(_ON, , _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, PetscDefaultFPTrap, _ABORT_ON_ERROR, 0);
313cc9df77eSBarry Smith else handle_sigfpes(_OFF, _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, 0, _ABORT_ON_ERROR, 0);
314670f3ff9SJed Brown _trapmode = flag;
315bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IRIX_STYLE_FPTRAP\n"));
3163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
317cc9df77eSBarry Smith }
318cc9df77eSBarry Smith
319d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
320d71ae5a4SJacob Faibussowitsch {
321cc9df77eSBarry Smith PetscFunctionBegin;
3229566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
3233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
324cc9df77eSBarry Smith }
325cc9df77eSBarry Smith
326cc9df77eSBarry Smith #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP)
327e5c89e4eSSatish Balay /* In "fast" mode, floating point traps are imprecise and ignored.
328e5c89e4eSSatish Balay This is the reason for the fptrap(FP_TRAP_SYNC) call */
329e5c89e4eSSatish Balay struct sigcontext;
330e5c89e4eSSatish Balay #include <fpxcp.h>
331e5c89e4eSSatish Balay #include <fptrap.h>
332e5c89e4eSSatish Balay #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000)
333e5c89e4eSSatish Balay #define FPE_FLTOVF_TRAP (fptrap_t)(0x10000000)
334e5c89e4eSSatish Balay #define FPE_FLTUND_TRAP (fptrap_t)(0x08000000)
335e5c89e4eSSatish Balay #define FPE_FLTDIV_TRAP (fptrap_t)(0x04000000)
336e5c89e4eSSatish Balay #define FPE_FLTINEX_TRAP (fptrap_t)(0x02000000)
337e5c89e4eSSatish Balay
3389371c9d4SSatish Balay static struct {
3399371c9d4SSatish Balay int code_no;
3409371c9d4SSatish Balay char *name;
3419371c9d4SSatish Balay } error_codes[] = {
342e5c89e4eSSatish Balay {FPE_FLTOPERR_TRAP, "IEEE operand error" },
343e5c89e4eSSatish Balay {FPE_FLTOVF_TRAP, "floating point overflow" },
344e5c89e4eSSatish Balay {FPE_FLTUND_TRAP, "floating point underflow" },
345e5c89e4eSSatish Balay {FPE_FLTDIV_TRAP, "floating point divide" },
346e5c89e4eSSatish Balay {FPE_FLTINEX_TRAP, "inexact floating point result"},
347bd2b07b1SBarry Smith < {0, "unknown error" }
348e5c89e4eSSatish Balay };
349e5c89e4eSSatish Balay #define SIGPC(scp) (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */
350e5c89e4eSSatish Balay /*
351e5c89e4eSSatish Balay For some reason, scp->sc_jmpbuf does not work on the RS6000, even though
352e5c89e4eSSatish Balay it looks like it should from the include definitions. It is probably
353e5c89e4eSSatish Balay some strange interaction with the "POSIX_SOURCE" that we require.
354e5c89e4eSSatish Balay */
355e5c89e4eSSatish Balay
356d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp)
357d71ae5a4SJacob Faibussowitsch {
358e5c89e4eSSatish Balay int err_ind, j;
359e5c89e4eSSatish Balay fp_ctx_t flt_context;
360e5c89e4eSSatish Balay
361e5c89e4eSSatish Balay PetscFunctionBegin;
362e5c89e4eSSatish Balay fp_sh_trap_info(scp, &flt_context);
363e5c89e4eSSatish Balay
364e5c89e4eSSatish Balay err_ind = -1;
365e5c89e4eSSatish Balay for (j = 0; error_codes[j].code_no; j++) {
366e5c89e4eSSatish Balay if (error_codes[j].code_no == flt_context.trap) err_ind = j;
367e5c89e4eSSatish Balay }
368e5c89e4eSSatish Balay
369dd460d27SBarry Smith if (err_ind >= 0) (void)(*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name);
370dd460d27SBarry Smith else (void)(*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", flt_context.trap);
371a297a907SKarl Rupp
372dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
37341e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
374e5c89e4eSSatish Balay }
375e5c89e4eSSatish Balay
376d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
377d71ae5a4SJacob Faibussowitsch {
378e5c89e4eSSatish Balay PetscFunctionBegin;
379bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) {
380e5c89e4eSSatish Balay signal(SIGFPE, (void (*)(int))PetscDefaultFPTrap);
381e5c89e4eSSatish Balay fp_trap(FP_TRAP_SYNC);
382bd2b07b1SBarry Smith /* fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); */
383bd2b07b1SBarry Smith fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
384e5c89e4eSSatish Balay } else {
385e5c89e4eSSatish Balay signal(SIGFPE, SIG_DFL);
386cc9df77eSBarry Smith fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW);
387e5c89e4eSSatish Balay fp_trap(FP_TRAP_OFF);
388e5c89e4eSSatish Balay }
389cf0818bdSBarry Smith _trapmode = flag;
390bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_RS6000_STYLE_FPTRAP\n"));
3913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
392e5c89e4eSSatish Balay }
393e5c89e4eSSatish Balay
394d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
395d71ae5a4SJacob Faibussowitsch {
396cc9df77eSBarry Smith PetscFunctionBegin;
3979566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
3983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
399cc9df77eSBarry Smith }
400cc9df77eSBarry Smith
401cc9df77eSBarry Smith #elif defined(PETSC_HAVE_WINDOWS_COMPILERS)
402cc9df77eSBarry Smith #include <float.h>
403d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
404d71ae5a4SJacob Faibussowitsch {
405cc9df77eSBarry Smith PetscFunctionBegin;
406dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** floating point error occurred ***\n");
407dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
408cc9df77eSBarry Smith PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
409cc9df77eSBarry Smith }
410cc9df77eSBarry Smith
411d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
412d71ae5a4SJacob Faibussowitsch {
413cc9df77eSBarry Smith unsigned int cw;
414cc9df77eSBarry Smith
415cc9df77eSBarry Smith PetscFunctionBegin;
416bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) {
417bd2b07b1SBarry Smith /* cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW; */
418bd2b07b1SBarry Smith cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW;
41908401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
420cc9df77eSBarry Smith } else {
421cc9df77eSBarry Smith cw = 0;
42208401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
423cc9df77eSBarry Smith }
424cc9df77eSBarry Smith (void)_controlfp(0, cw);
425cf0818bdSBarry Smith _trapmode = flag;
426bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_WINDOWS_COMPILERS FPTRAP\n"));
4273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
428cc9df77eSBarry Smith }
429cc9df77eSBarry Smith
430d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
431d71ae5a4SJacob Faibussowitsch {
432cc9df77eSBarry Smith PetscFunctionBegin;
4339566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
4343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
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>
448accbd18bSBarry Smith #if defined(PETSC_HAVE_FE_VALUES)
4499371c9d4SSatish Balay typedef struct {
4509371c9d4SSatish Balay int code;
4519371c9d4SSatish Balay const char *name;
4529371c9d4SSatish Balay } FPNode;
453b014e56cSJed Brown static const FPNode error_codes[] = {
454b014e56cSJed Brown {FE_DIVBYZERO, "divide by zero" },
455b014e56cSJed Brown {FE_INEXACT, "inexact floating point result" },
456b014e56cSJed Brown {FE_INVALID, "invalid floating point arguments (domain error)"},
457b014e56cSJed Brown {FE_OVERFLOW, "floating point overflow" },
458b014e56cSJed Brown {FE_UNDERFLOW, "floating point underflow" },
459b014e56cSJed Brown {0, "unknown error" }
460b014e56cSJed Brown };
461accbd18bSBarry Smith #endif
46299e0435eSBarry Smith
463d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
464d71ae5a4SJacob Faibussowitsch {
465accbd18bSBarry Smith #if defined(PETSC_HAVE_FE_VALUES)
466b014e56cSJed Brown const FPNode *node;
467b014e56cSJed Brown int code;
468ace3abfcSBarry Smith PetscBool matched = PETSC_FALSE;
469accbd18bSBarry Smith #endif
470b014e56cSJed Brown
471b014e56cSJed Brown PetscFunctionBegin;
472b014e56cSJed Brown /* Note: While it is possible for the exception state to be preserved by the
473b014e56cSJed Brown * kernel, this seems to be rare which makes the following flag testing almost
474b014e56cSJed Brown * useless. But on a system where the flags can be preserved, it would provide
4757d125cddSJed Brown * more detail.
476b014e56cSJed Brown */
477accbd18bSBarry Smith #if defined(PETSC_HAVE_FE_VALUES)
478b014e56cSJed Brown code = fetestexcept(FE_ALL_EXCEPT);
479b014e56cSJed Brown for (node = &error_codes[0]; node->code; node++) {
480b014e56cSJed Brown if (code & node->code) {
481b014e56cSJed Brown matched = PETSC_TRUE;
482dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** floating point error \"%s\" occurred ***\n", node->name);
483b014e56cSJed Brown code &= ~node->code; /* Unset this flag since it has been processed */
484b014e56cSJed Brown }
485b014e56cSJed Brown }
486b014e56cSJed Brown if (!matched || code) { /* If any remaining flags are set, or we didn't process any flags */
487dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** unknown floating point error occurred ***\n");
488dd460d27SBarry Smith (void)(*PetscErrorPrintf)("The specific exception can be determined by running in a debugger. When the\n");
489dd460d27SBarry Smith (void)(*PetscErrorPrintf)("debugger traps the signal, the exception can be found with fetestexcept(0x%x)\n", FE_ALL_EXCEPT);
490dd460d27SBarry Smith (void)(*PetscErrorPrintf)("where the result is a bitwise OR of the following flags:\n");
491dd460d27SBarry Smith (void)(*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);
492b014e56cSJed Brown }
493accbd18bSBarry Smith #else
494dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** unknown floating point error occurred ***\n");
495accbd18bSBarry Smith #endif
4967d125cddSJed Brown
497dd460d27SBarry Smith (void)(*PetscErrorPrintf)("Try option -start_in_debugger\n");
49827104ee2SJacob Faibussowitsch #if PetscDefined(USE_DEBUG)
499dfb7d7afSStefano Zampini #if !PetscDefined(HAVE_THREADSAFETY)
500dd460d27SBarry Smith (void)(*PetscErrorPrintf)("likely location of problem given in stack below\n");
501dd460d27SBarry Smith (void)(*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n");
502dd460d27SBarry Smith (void)PetscStackView(PETSC_STDOUT);
503dfb7d7afSStefano Zampini #endif
50427104ee2SJacob Faibussowitsch #else
505dd460d27SBarry Smith (void)(*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
506dd460d27SBarry Smith (void)(*PetscErrorPrintf)("with -start_in_debugger to get more information on the crash.\n");
50727104ee2SJacob Faibussowitsch #endif
508dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_INITIAL, "trapped floating point error");
50941e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
510b014e56cSJed Brown }
511b014e56cSJed Brown
512d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
513d71ae5a4SJacob Faibussowitsch {
514b014e56cSJed Brown PetscFunctionBegin;
515bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) {
516b014e56cSJed Brown /* Clear any flags that are currently set so that activating trapping will not immediately call the signal handler. */
517cc73adaaSBarry Smith PetscCheck(!feclearexcept(FE_ALL_EXCEPT), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot clear floating point exception flags");
518accbd18bSBarry Smith #if defined(FE_NOMASK_ENV) && defined(PETSC_HAVE_FE_VALUES)
519cc9df77eSBarry Smith /* Could use fesetenv(FE_NOMASK_ENV), but that causes spurious exceptions (like gettimeofday() -> PetscLogDouble). */
520cf0818bdSBarry Smith /* PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) != -1,PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot activate floating point exceptions"); */
521bd2b07b1SBarry Smith /* Doesn't work on AArch64 targets. There's a known hardware limitation. Need to detect hardware at configure time? */
522cf0818bdSBarry Smith PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW) != -1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot activate floating point exceptions");
523bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with FE_NOMASK_ENV\n"));
524b014e56cSJed Brown #elif defined PETSC_HAVE_XMMINTRIN_H
525cc9df77eSBarry Smith _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_DIV_ZERO);
526bd2b07b1SBarry Smith /* _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_UNDERFLOW); */
527cc9df77eSBarry Smith _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_OVERFLOW);
528cc9df77eSBarry Smith _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID);
529bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with PETSC_HAVE_XMMINTRIN_H\n"));
530b014e56cSJed Brown #else
531b014e56cSJed Brown /* C99 does not provide a way to modify the environment so there is no portable way to activate trapping. */
532bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP\n"));
533b014e56cSJed Brown #endif
53408401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
535b014e56cSJed Brown } else {
536cc73adaaSBarry Smith PetscCheck(!fesetenv(FE_DFL_ENV), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot disable floating point exceptions");
537cc9df77eSBarry Smith /* can use _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | _MM_MASK_UNDERFLOW); if PETSC_HAVE_XMMINTRIN_H exists */
53808401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
539b014e56cSJed Brown }
540cf0818bdSBarry Smith _trapmode = flag;
5413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
542b014e56cSJed Brown }
543b014e56cSJed Brown
544d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
545d71ae5a4SJacob Faibussowitsch {
546cc9df77eSBarry Smith #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
547cc9df77eSBarry Smith unsigned int flags;
548cc9df77eSBarry Smith #endif
549cc9df77eSBarry Smith
550cc9df77eSBarry Smith PetscFunctionBegin;
551cc9df77eSBarry Smith #if defined(FE_NOMASK_ENV)
552cc9df77eSBarry Smith flags = fegetexcept();
553cc9df77eSBarry Smith if (flags & FE_DIVBYZERO) {
554cc9df77eSBarry Smith #elif defined PETSC_HAVE_XMMINTRIN_H
555cc9df77eSBarry Smith flags = _MM_GET_EXCEPTION_MASK();
556cc9df77eSBarry Smith if (!(flags & _MM_MASK_DIV_ZERO)) {
557cc9df77eSBarry Smith #else
5589566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Floating point trapping unknown, assuming off\n"));
5593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
560cc9df77eSBarry Smith #endif
561cc9df77eSBarry Smith #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
562cc9df77eSBarry Smith _trapmode = PETSC_FP_TRAP_ON;
5639566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Floating point trapping is on by default %d\n", flags));
564cc9df77eSBarry Smith } else {
565cc9df77eSBarry Smith _trapmode = PETSC_FP_TRAP_OFF;
5669566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Floating point trapping is off by default %d\n", flags));
567cc9df77eSBarry Smith }
5683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
569cc9df77eSBarry Smith #endif
570cc9df77eSBarry Smith }
571cc9df77eSBarry Smith
572cc9df77eSBarry Smith #elif defined(PETSC_HAVE_IEEEFP_H)
573cc9df77eSBarry Smith #include <ieeefp.h>
574d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig)
575d71ae5a4SJacob Faibussowitsch {
576cc9df77eSBarry Smith PetscFunctionBegin;
577dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** floating point error occurred ***\n");
578dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
579cc9df77eSBarry Smith PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
580cc9df77eSBarry Smith }
581cc9df77eSBarry Smith
582d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
583d71ae5a4SJacob Faibussowitsch {
584cc9df77eSBarry Smith PetscFunctionBegin;
585cf0818bdSBarry Smith if (flag == PETSC_FP_TRAP_ON) {
58618da0197SPierre Jolivet #if defined(PETSC_HAVE_FPRESETSTICKY)
587cc9df77eSBarry Smith fpresetsticky(fpgetsticky());
588cc9df77eSBarry Smith #elif defined(PETSC_HAVE_FPSETSTICKY)
589cc9df77eSBarry Smith fpsetsticky(fpgetsticky());
590cc9df77eSBarry Smith #endif
591cc9df77eSBarry Smith fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_OFL);
59208401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler");
593cc9df77eSBarry Smith } else {
59418da0197SPierre Jolivet #if defined(PETSC_HAVE_FPRESETSTICKY)
595cc9df77eSBarry Smith fpresetsticky(fpgetsticky());
596cc9df77eSBarry Smith #elif defined(PETSC_HAVE_FPSETSTICKY)
597cc9df77eSBarry Smith fpsetsticky(fpgetsticky());
598cc9df77eSBarry Smith #endif
599cc9df77eSBarry Smith fpsetmask(0);
60008401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler");
601cc9df77eSBarry Smith }
602cf0818bdSBarry Smith _trapmode = flag;
603bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IEEEFP_H FPTRAP\n"));
6043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
605cc9df77eSBarry Smith }
606cc9df77eSBarry Smith
607d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
608d71ae5a4SJacob Faibussowitsch {
609cc9df77eSBarry Smith PetscFunctionBegin;
6109566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
6113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
612cc9df77eSBarry Smith }
613cc9df77eSBarry Smith
614*21789920SBarry Smith /* Default */
615e5c89e4eSSatish Balay #else
61699e0435eSBarry Smith
61766976f2fSJacob Faibussowitsch static void PetscDefaultFPTrap(int sig)
618d71ae5a4SJacob Faibussowitsch {
619e5c89e4eSSatish Balay PetscFunctionBegin;
620dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** floating point error occurred ***\n");
621dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error");
62241e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP);
623e5c89e4eSSatish Balay }
62499e0435eSBarry Smith
625d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
626d71ae5a4SJacob Faibussowitsch {
627e5c89e4eSSatish Balay PetscFunctionBegin;
628bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) {
6293ba16761SJacob Faibussowitsch if (SIG_ERR == signal(SIGFPE, PetscDefaultFPTrap)) PetscCall((*PetscErrorPrintf)("Can't set floatingpoint handler\n"));
6303ba16761SJacob Faibussowitsch } else if (SIG_ERR == signal(SIGFPE, SIG_DFL)) PetscCall((*PetscErrorPrintf)("Can't clear floatingpoint handler\n"));
631a297a907SKarl Rupp
632cf0818bdSBarry Smith _trapmode = flag;
633bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using default FPTRAP\n"));
6343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
635e5c89e4eSSatish Balay }
636cc9df77eSBarry Smith
637d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void)
638d71ae5a4SJacob Faibussowitsch {
639cc9df77eSBarry Smith PetscFunctionBegin;
6409566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n"));
6413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
642cc9df77eSBarry Smith }
643e5c89e4eSSatish Balay #endif
644