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 @*/ 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 @*/ 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 /*--------------------------------------- ---------------------------------------------------*/ 100e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP) 101e5c89e4eSSatish Balay #include <floatingpoint.h> 102e5c89e4eSSatish Balay 1038cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_flags(char *, char *, char *, char **); 1048cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_handler(char *, char *, sigfpe_handler_type(int, int, struct sigcontext *, char *)); 105e5c89e4eSSatish Balay 1069371c9d4SSatish Balay static struct { 1079371c9d4SSatish Balay int code_no; 1089371c9d4SSatish Balay char *name; 1099371c9d4SSatish Balay } error_codes[] = { 110e5c89e4eSSatish Balay {FPE_INTDIV_TRAP, "integer divide" }, 111e5c89e4eSSatish Balay {FPE_FLTOPERR_TRAP, "IEEE operand error" }, 112e5c89e4eSSatish Balay {FPE_FLTOVF_TRAP, "floating point overflow" }, 113e5c89e4eSSatish Balay {FPE_FLTUND_TRAP, "floating point underflow" }, 114e5c89e4eSSatish Balay {FPE_FLTDIV_TRAP, "floating pointing divide" }, 115e5c89e4eSSatish Balay {FPE_FLTINEX_TRAP, "inexact floating point result"}, 116e5c89e4eSSatish Balay {0, "unknown error" } 117e5c89e4eSSatish Balay }; 118e5c89e4eSSatish Balay #define SIGPC(scp) (scp->sc_pc) 119e5c89e4eSSatish Balay 120cf0818bdSBarry Smith /* this function gets called if a trap has occurred and been caught */ 121d71ae5a4SJacob Faibussowitsch sigfpe_handler_type PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp, char *addr) 122d71ae5a4SJacob Faibussowitsch { 1235f80ce2aSJacob Faibussowitsch int err_ind = -1; 124e5c89e4eSSatish Balay 125e5c89e4eSSatish Balay PetscFunctionBegin; 1265f80ce2aSJacob Faibussowitsch for (int j = 0; error_codes[j].code_no; j++) { 127e5c89e4eSSatish Balay if (error_codes[j].code_no == code) err_ind = j; 128e5c89e4eSSatish Balay } 129e5c89e4eSSatish Balay 130*dd460d27SBarry Smith if (err_ind >= 0) (void)(*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp)); 131*dd460d27SBarry Smith else (void)(*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp)); 132a297a907SKarl Rupp 133*dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, PETSC_ERR_FP, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 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: 1637de69702SBarry Smith Preferred usage is `PetscFPTrapPush()` and `PetscFPTrapPop()` instead of this routine 1647de69702SBarry 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: 211337bb527SBarry 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; 247e5c89e4eSSatish Balay 248e5c89e4eSSatish Balay PetscFunctionBegin; 2495f80ce2aSJacob Faibussowitsch for (int j = 0; error_codes[j].code_no; j++) { 250e5c89e4eSSatish Balay if (error_codes[j].code_no == code) err_ind = j; 251e5c89e4eSSatish Balay } 252e5c89e4eSSatish Balay 253*dd460d27SBarry Smith if (err_ind >= 0) (void)(*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp)); 254*dd460d27SBarry Smith else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp)); 255a297a907SKarl Rupp 256*dd460d27SBarry Smith PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 25741e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 258e5c89e4eSSatish Balay } 259e5c89e4eSSatish Balay 260d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 261d71ae5a4SJacob Faibussowitsch { 262e5c89e4eSSatish Balay char *out; 263e5c89e4eSSatish Balay 264e5c89e4eSSatish Balay PetscFunctionBegin; 265e5c89e4eSSatish Balay /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */ 266e5c89e4eSSatish Balay (void)ieee_flags("clear", "exception", "all", &out); 267e5c89e4eSSatish Balay if (flag == PETSC_FP_TRAP_ON) { 268a297a907SKarl Rupp if (ieee_handler("set", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n"); 269cc9df77eSBarry Smith } else { 270cc9df77eSBarry Smith if (ieee_handler("clear", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 271cc9df77eSBarry Smith } 272670f3ff9SJed Brown _trapmode = flag; 273bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL,"Using PETSC_HAVE_SOLARIS_STYLE_FPTRAP\n"); 2743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 275e5c89e4eSSatish Balay } 276e5c89e4eSSatish Balay 277d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 278d71ae5a4SJacob Faibussowitsch { 279cc9df77eSBarry Smith PetscFunctionBegin; 2809566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 2813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 282cc9df77eSBarry Smith } 283cc9df77eSBarry Smith 284cc9df77eSBarry Smith /* ------------------------------------------------------------------------------------------*/ 285e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_IRIX_STYLE_FPTRAP) 286e5c89e4eSSatish Balay #include <sigfpe.h> 2879371c9d4SSatish Balay static struct { 2889371c9d4SSatish Balay int code_no; 2899371c9d4SSatish Balay char *name; 2909371c9d4SSatish Balay } error_codes[] = { 291e5c89e4eSSatish Balay {_INVALID, "IEEE operand error" }, 292e5c89e4eSSatish Balay {_OVERFL, "floating point overflow" }, 293e5c89e4eSSatish Balay {_UNDERFL, "floating point underflow"}, 294e5c89e4eSSatish Balay {_DIVZERO, "floating point divide" }, 295e5c89e4eSSatish Balay {0, "unknown error" } 296e5c89e4eSSatish Balay }; 297d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(unsigned exception[], int val[]) 298d71ae5a4SJacob Faibussowitsch { 2995f80ce2aSJacob Faibussowitsch int err_ind = -1, code = exception[0]; 300e5c89e4eSSatish Balay 301e5c89e4eSSatish Balay PetscFunctionBegin; 3025f80ce2aSJacob Faibussowitsch for (int j = 0; error_codes[j].code_no; j++) { 303e5c89e4eSSatish Balay if (error_codes[j].code_no == code) err_ind = j; 304e5c89e4eSSatish Balay } 305*dd460d27SBarry Smith if (err_ind >= 0) (void)(*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name); 306*dd460d27SBarry Smith else (void)(*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", code); 307a297a907SKarl Rupp 308*dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 30941e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 310e5c89e4eSSatish Balay } 311e5c89e4eSSatish Balay 312d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 313d71ae5a4SJacob Faibussowitsch { 314e5c89e4eSSatish Balay PetscFunctionBegin; 315bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) handle_sigfpes(_ON, , _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, PetscDefaultFPTrap, _ABORT_ON_ERROR, 0); 316cc9df77eSBarry Smith else handle_sigfpes(_OFF, _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, 0, _ABORT_ON_ERROR, 0); 317670f3ff9SJed Brown _trapmode = flag; 318bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IRIX_STYLE_FPTRAP\n")); 3193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 320cc9df77eSBarry Smith } 321cc9df77eSBarry Smith 322d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 323d71ae5a4SJacob Faibussowitsch { 324cc9df77eSBarry Smith PetscFunctionBegin; 3259566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 3263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 327cc9df77eSBarry Smith } 328cc9df77eSBarry Smith 329cc9df77eSBarry Smith /*----------------------------------------------- --------------------------------------------*/ 330cc9df77eSBarry Smith #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP) 331e5c89e4eSSatish Balay /* In "fast" mode, floating point traps are imprecise and ignored. 332e5c89e4eSSatish Balay This is the reason for the fptrap(FP_TRAP_SYNC) call */ 333e5c89e4eSSatish Balay struct sigcontext; 334e5c89e4eSSatish Balay #include <fpxcp.h> 335e5c89e4eSSatish Balay #include <fptrap.h> 336e5c89e4eSSatish Balay #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000) 337e5c89e4eSSatish Balay #define FPE_FLTOVF_TRAP (fptrap_t)(0x10000000) 338e5c89e4eSSatish Balay #define FPE_FLTUND_TRAP (fptrap_t)(0x08000000) 339e5c89e4eSSatish Balay #define FPE_FLTDIV_TRAP (fptrap_t)(0x04000000) 340e5c89e4eSSatish Balay #define FPE_FLTINEX_TRAP (fptrap_t)(0x02000000) 341e5c89e4eSSatish Balay 3429371c9d4SSatish Balay static struct { 3439371c9d4SSatish Balay int code_no; 3449371c9d4SSatish Balay char *name; 3459371c9d4SSatish Balay } error_codes[] = { 346e5c89e4eSSatish Balay {FPE_FLTOPERR_TRAP, "IEEE operand error" }, 347e5c89e4eSSatish Balay {FPE_FLTOVF_TRAP, "floating point overflow" }, 348e5c89e4eSSatish Balay {FPE_FLTUND_TRAP, "floating point underflow" }, 349e5c89e4eSSatish Balay {FPE_FLTDIV_TRAP, "floating point divide" }, 350e5c89e4eSSatish Balay {FPE_FLTINEX_TRAP, "inexact floating point result"}, 351bd2b07b1SBarry Smith < {0, "unknown error" } 352e5c89e4eSSatish Balay }; 353e5c89e4eSSatish Balay #define SIGPC(scp) (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */ 354e5c89e4eSSatish Balay /* 355e5c89e4eSSatish Balay For some reason, scp->sc_jmpbuf does not work on the RS6000, even though 356e5c89e4eSSatish Balay it looks like it should from the include definitions. It is probably 357e5c89e4eSSatish Balay some strange interaction with the "POSIX_SOURCE" that we require. 358e5c89e4eSSatish Balay */ 359e5c89e4eSSatish Balay 360d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp) 361d71ae5a4SJacob Faibussowitsch { 362e5c89e4eSSatish Balay int err_ind, j; 363e5c89e4eSSatish Balay fp_ctx_t flt_context; 364e5c89e4eSSatish Balay 365e5c89e4eSSatish Balay PetscFunctionBegin; 366e5c89e4eSSatish Balay fp_sh_trap_info(scp, &flt_context); 367e5c89e4eSSatish Balay 368e5c89e4eSSatish Balay err_ind = -1; 369e5c89e4eSSatish Balay for (j = 0; error_codes[j].code_no; j++) { 370e5c89e4eSSatish Balay if (error_codes[j].code_no == flt_context.trap) err_ind = j; 371e5c89e4eSSatish Balay } 372e5c89e4eSSatish Balay 373*dd460d27SBarry Smith if (err_ind >= 0) (void)(*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name); 374*dd460d27SBarry Smith else (void)(*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", flt_context.trap); 375a297a907SKarl Rupp 376*dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 37741e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 378e5c89e4eSSatish Balay } 379e5c89e4eSSatish Balay 380d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 381d71ae5a4SJacob Faibussowitsch { 382e5c89e4eSSatish Balay PetscFunctionBegin; 383bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) { 384e5c89e4eSSatish Balay signal(SIGFPE, (void (*)(int))PetscDefaultFPTrap); 385e5c89e4eSSatish Balay fp_trap(FP_TRAP_SYNC); 386bd2b07b1SBarry Smith /* fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); */ 387bd2b07b1SBarry Smith fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW); 388e5c89e4eSSatish Balay } else { 389e5c89e4eSSatish Balay signal(SIGFPE, SIG_DFL); 390cc9df77eSBarry Smith fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); 391e5c89e4eSSatish Balay fp_trap(FP_TRAP_OFF); 392e5c89e4eSSatish Balay } 393cf0818bdSBarry Smith _trapmode = flag; 394bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_RS6000_STYLE_FPTRAP\n")); 3953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 396e5c89e4eSSatish Balay } 397e5c89e4eSSatish Balay 398d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 399d71ae5a4SJacob Faibussowitsch { 400cc9df77eSBarry Smith PetscFunctionBegin; 4019566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 4023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 403cc9df77eSBarry Smith } 404cc9df77eSBarry Smith 405cc9df77eSBarry Smith /* ------------------------------------------------------------*/ 406cc9df77eSBarry Smith #elif defined(PETSC_HAVE_WINDOWS_COMPILERS) 407cc9df77eSBarry Smith #include <float.h> 408d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig) 409d71ae5a4SJacob Faibussowitsch { 410cc9df77eSBarry Smith PetscFunctionBegin; 411*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** floating point error occurred ***\n"); 412*dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 413cc9df77eSBarry Smith PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 414cc9df77eSBarry Smith } 415cc9df77eSBarry Smith 416d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 417d71ae5a4SJacob Faibussowitsch { 418cc9df77eSBarry Smith unsigned int cw; 419cc9df77eSBarry Smith 420cc9df77eSBarry Smith PetscFunctionBegin; 421bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) { 422bd2b07b1SBarry Smith /* cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW; */ 423bd2b07b1SBarry Smith cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW; 42408401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler"); 425cc9df77eSBarry Smith } else { 426cc9df77eSBarry Smith cw = 0; 42708401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler"); 428cc9df77eSBarry Smith } 429cc9df77eSBarry Smith (void)_controlfp(0, cw); 430cf0818bdSBarry Smith _trapmode = flag; 431bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_WINDOWS_COMPILERS FPTRAP\n")); 4323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 433cc9df77eSBarry Smith } 434cc9df77eSBarry Smith 435d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 436d71ae5a4SJacob Faibussowitsch { 437cc9df77eSBarry Smith PetscFunctionBegin; 4389566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 4393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 440cc9df77eSBarry Smith } 441cc9df77eSBarry Smith 442cc9df77eSBarry Smith /* ------------------------------------------------------------*/ 4439a2402e9SBarry Smith #elif defined(PETSC_HAVE_FENV_H) && !defined(__cplusplus) 444b014e56cSJed Brown /* 445b014e56cSJed Brown C99 style floating point environment. 446b014e56cSJed Brown 447b014e56cSJed Brown Note that C99 merely specifies how to save, restore, and clear the floating 448b014e56cSJed Brown point environment as well as defining an enumeration of exception codes. In 449b014e56cSJed Brown particular, C99 does not specify how to make floating point exceptions raise 450b014e56cSJed Brown a signal. Glibc offers this capability through FE_NOMASK_ENV (or with finer 451b014e56cSJed Brown granularity, feenableexcept()), xmmintrin.h offers _MM_SET_EXCEPTION_MASK(). 452b014e56cSJed Brown */ 453b014e56cSJed Brown #include <fenv.h> 454accbd18bSBarry Smith #if defined(PETSC_HAVE_FE_VALUES) 4559371c9d4SSatish Balay typedef struct { 4569371c9d4SSatish Balay int code; 4579371c9d4SSatish Balay const char *name; 4589371c9d4SSatish Balay } FPNode; 459b014e56cSJed Brown static const FPNode error_codes[] = { 460b014e56cSJed Brown {FE_DIVBYZERO, "divide by zero" }, 461b014e56cSJed Brown {FE_INEXACT, "inexact floating point result" }, 462b014e56cSJed Brown {FE_INVALID, "invalid floating point arguments (domain error)"}, 463b014e56cSJed Brown {FE_OVERFLOW, "floating point overflow" }, 464b014e56cSJed Brown {FE_UNDERFLOW, "floating point underflow" }, 465b014e56cSJed Brown {0, "unknown error" } 466b014e56cSJed Brown }; 467accbd18bSBarry Smith #endif 46899e0435eSBarry Smith 469d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig) 470d71ae5a4SJacob Faibussowitsch { 471accbd18bSBarry Smith #if defined(PETSC_HAVE_FE_VALUES) 472b014e56cSJed Brown const FPNode *node; 473b014e56cSJed Brown int code; 474ace3abfcSBarry Smith PetscBool matched = PETSC_FALSE; 475accbd18bSBarry Smith #endif 476b014e56cSJed Brown 477b014e56cSJed Brown PetscFunctionBegin; 478b014e56cSJed Brown /* Note: While it is possible for the exception state to be preserved by the 479b014e56cSJed Brown * kernel, this seems to be rare which makes the following flag testing almost 480b014e56cSJed Brown * useless. But on a system where the flags can be preserved, it would provide 4817d125cddSJed Brown * more detail. 482b014e56cSJed Brown */ 483accbd18bSBarry Smith #if defined(PETSC_HAVE_FE_VALUES) 484b014e56cSJed Brown code = fetestexcept(FE_ALL_EXCEPT); 485b014e56cSJed Brown for (node = &error_codes[0]; node->code; node++) { 486b014e56cSJed Brown if (code & node->code) { 487b014e56cSJed Brown matched = PETSC_TRUE; 488*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** floating point error \"%s\" occurred ***\n", node->name); 489b014e56cSJed Brown code &= ~node->code; /* Unset this flag since it has been processed */ 490b014e56cSJed Brown } 491b014e56cSJed Brown } 492b014e56cSJed Brown if (!matched || code) { /* If any remaining flags are set, or we didn't process any flags */ 493*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** unknown floating point error occurred ***\n"); 494*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("The specific exception can be determined by running in a debugger. When the\n"); 495*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("debugger traps the signal, the exception can be found with fetestexcept(0x%x)\n", FE_ALL_EXCEPT); 496*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("where the result is a bitwise OR of the following flags:\n"); 497*dd460d27SBarry 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); 498b014e56cSJed Brown } 499accbd18bSBarry Smith #else 500*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** unknown floating point error occurred ***\n"); 501accbd18bSBarry Smith #endif 5027d125cddSJed Brown 503*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("Try option -start_in_debugger\n"); 50427104ee2SJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 505dfb7d7afSStefano Zampini #if !PetscDefined(HAVE_THREADSAFETY) 506*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("likely location of problem given in stack below\n"); 507*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n"); 508*dd460d27SBarry Smith (void)PetscStackView(PETSC_STDOUT); 509dfb7d7afSStefano Zampini #endif 51027104ee2SJacob Faibussowitsch #else 511*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n"); 512*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("with -start_in_debugger to get more information on the crash.\n"); 51327104ee2SJacob Faibussowitsch #endif 514*dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_INITIAL, "trapped floating point error"); 51541e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 516b014e56cSJed Brown } 517b014e56cSJed Brown 518d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 519d71ae5a4SJacob Faibussowitsch { 520b014e56cSJed Brown PetscFunctionBegin; 521bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) { 522b014e56cSJed Brown /* Clear any flags that are currently set so that activating trapping will not immediately call the signal handler. */ 523cc73adaaSBarry Smith PetscCheck(!feclearexcept(FE_ALL_EXCEPT), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot clear floating point exception flags"); 524accbd18bSBarry Smith #if defined(FE_NOMASK_ENV) && defined(PETSC_HAVE_FE_VALUES) 525cc9df77eSBarry Smith /* Could use fesetenv(FE_NOMASK_ENV), but that causes spurious exceptions (like gettimeofday() -> PetscLogDouble). */ 526cf0818bdSBarry Smith /* PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) != -1,PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot activate floating point exceptions"); */ 527bd2b07b1SBarry Smith /* Doesn't work on AArch64 targets. There's a known hardware limitation. Need to detect hardware at configure time? */ 528cf0818bdSBarry Smith PetscCheck(feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW) != -1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot activate floating point exceptions"); 529bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with FE_NOMASK_ENV\n")); 530b014e56cSJed Brown #elif defined PETSC_HAVE_XMMINTRIN_H 531cc9df77eSBarry Smith _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_DIV_ZERO); 532bd2b07b1SBarry Smith /* _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_UNDERFLOW); */ 533cc9df77eSBarry Smith _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_OVERFLOW); 534cc9df77eSBarry Smith _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID); 535bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP with PETSC_HAVE_XMMINTRIN_H\n")); 536b014e56cSJed Brown #else 537b014e56cSJed Brown /* C99 does not provide a way to modify the environment so there is no portable way to activate trapping. */ 538bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_FENV_H FPTRAP\n")); 539b014e56cSJed Brown #endif 54008401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler"); 541b014e56cSJed Brown } else { 542cc73adaaSBarry Smith PetscCheck(!fesetenv(FE_DFL_ENV), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot disable floating point exceptions"); 543cc9df77eSBarry Smith /* can use _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | _MM_MASK_UNDERFLOW); if PETSC_HAVE_XMMINTRIN_H exists */ 54408401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler"); 545b014e56cSJed Brown } 546cf0818bdSBarry Smith _trapmode = flag; 5473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 548b014e56cSJed Brown } 549b014e56cSJed Brown 550d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 551d71ae5a4SJacob Faibussowitsch { 552cc9df77eSBarry Smith #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H 553cc9df77eSBarry Smith unsigned int flags; 554cc9df77eSBarry Smith #endif 555cc9df77eSBarry Smith 556cc9df77eSBarry Smith PetscFunctionBegin; 557cc9df77eSBarry Smith #if defined(FE_NOMASK_ENV) 558cc9df77eSBarry Smith flags = fegetexcept(); 559cc9df77eSBarry Smith if (flags & FE_DIVBYZERO) { 560cc9df77eSBarry Smith #elif defined PETSC_HAVE_XMMINTRIN_H 561cc9df77eSBarry Smith flags = _MM_GET_EXCEPTION_MASK(); 562cc9df77eSBarry Smith if (!(flags & _MM_MASK_DIV_ZERO)) { 563cc9df77eSBarry Smith #else 5649566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Floating point trapping unknown, assuming off\n")); 5653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 566cc9df77eSBarry Smith #endif 567cc9df77eSBarry Smith #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H 568cc9df77eSBarry Smith _trapmode = PETSC_FP_TRAP_ON; 5699566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Floating point trapping is on by default %d\n", flags)); 570cc9df77eSBarry Smith } else { 571cc9df77eSBarry Smith _trapmode = PETSC_FP_TRAP_OFF; 5729566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Floating point trapping is off by default %d\n", flags)); 573cc9df77eSBarry Smith } 5743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 575cc9df77eSBarry Smith #endif 576cc9df77eSBarry Smith } 577cc9df77eSBarry Smith 578cc9df77eSBarry Smith /* ------------------------------------------------------------*/ 579cc9df77eSBarry Smith #elif defined(PETSC_HAVE_IEEEFP_H) 580cc9df77eSBarry Smith #include <ieeefp.h> 581d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig) 582d71ae5a4SJacob Faibussowitsch { 583cc9df77eSBarry Smith PetscFunctionBegin; 584*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** floating point error occurred ***\n"); 585*dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 586cc9df77eSBarry Smith PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 587cc9df77eSBarry Smith } 588cc9df77eSBarry Smith 589d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 590d71ae5a4SJacob Faibussowitsch { 591cc9df77eSBarry Smith PetscFunctionBegin; 592cf0818bdSBarry Smith if (flag == PETSC_FP_TRAP_ON) { 59318da0197SPierre Jolivet #if defined(PETSC_HAVE_FPRESETSTICKY) 594cc9df77eSBarry Smith fpresetsticky(fpgetsticky()); 595cc9df77eSBarry Smith #elif defined(PETSC_HAVE_FPSETSTICKY) 596cc9df77eSBarry Smith fpsetsticky(fpgetsticky()); 597cc9df77eSBarry Smith #endif 598cc9df77eSBarry Smith fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_OFL); 59908401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler"); 600cc9df77eSBarry Smith } else { 60118da0197SPierre Jolivet #if defined(PETSC_HAVE_FPRESETSTICKY) 602cc9df77eSBarry Smith fpresetsticky(fpgetsticky()); 603cc9df77eSBarry Smith #elif defined(PETSC_HAVE_FPSETSTICKY) 604cc9df77eSBarry Smith fpsetsticky(fpgetsticky()); 605cc9df77eSBarry Smith #endif 606cc9df77eSBarry Smith fpsetmask(0); 60708401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler"); 608cc9df77eSBarry Smith } 609cf0818bdSBarry Smith _trapmode = flag; 610bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IEEEFP_H FPTRAP\n")); 6113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 612cc9df77eSBarry Smith } 613cc9df77eSBarry Smith 614d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 615d71ae5a4SJacob Faibussowitsch { 616cc9df77eSBarry Smith PetscFunctionBegin; 6179566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 6183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 619cc9df77eSBarry Smith } 620cc9df77eSBarry Smith 621e5c89e4eSSatish Balay /* -------------------------Default -----------------------------------*/ 622e5c89e4eSSatish Balay #else 62399e0435eSBarry Smith 62466976f2fSJacob Faibussowitsch static void PetscDefaultFPTrap(int sig) 625d71ae5a4SJacob Faibussowitsch { 626e5c89e4eSSatish Balay PetscFunctionBegin; 627*dd460d27SBarry Smith (void)(*PetscErrorPrintf)("*** floating point error occurred ***\n"); 628*dd460d27SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 62941e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 630e5c89e4eSSatish Balay } 63199e0435eSBarry Smith 632d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 633d71ae5a4SJacob Faibussowitsch { 634e5c89e4eSSatish Balay PetscFunctionBegin; 635bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) { 6363ba16761SJacob Faibussowitsch if (SIG_ERR == signal(SIGFPE, PetscDefaultFPTrap)) PetscCall((*PetscErrorPrintf)("Can't set floatingpoint handler\n")); 6373ba16761SJacob Faibussowitsch } else if (SIG_ERR == signal(SIGFPE, SIG_DFL)) PetscCall((*PetscErrorPrintf)("Can't clear floatingpoint handler\n")); 638a297a907SKarl Rupp 639cf0818bdSBarry Smith _trapmode = flag; 640bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using default FPTRAP\n")); 6413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 642e5c89e4eSSatish Balay } 643cc9df77eSBarry Smith 644d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 645d71ae5a4SJacob Faibussowitsch { 646cc9df77eSBarry Smith PetscFunctionBegin; 6479566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 6483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 649cc9df77eSBarry Smith } 650e5c89e4eSSatish Balay #endif 651