17d0a6c19SBarry Smith 2e5c89e4eSSatish Balay /* 30e3d61c9SBarry Smith IEEE error handler for all machines. Since each OS has 40e3d61c9SBarry Smith enough slight differences we have completely separate codes for each one. 5e5c89e4eSSatish Balay */ 6b014e56cSJed Brown 7b014e56cSJed Brown /* 8b014e56cSJed Brown This feature test macro provides FE_NOMASK_ENV on GNU. It must be defined 9b014e56cSJed Brown at the top of the file because other headers may pull in fenv.h even when 10b014e56cSJed Brown not strictly necessary. Strictly speaking, we could include ONLY petscconf.h, 11b014e56cSJed Brown check PETSC_HAVE_FENV_H, and only define _GNU_SOURCE in that case, but such 12b014e56cSJed Brown shenanigans ought to be unnecessary. 13b014e56cSJed Brown */ 14519f805aSKarl Rupp #if !defined(_GNU_SOURCE) 15b014e56cSJed Brown #define _GNU_SOURCE 1676a6984eSJed Brown #endif 17b014e56cSJed Brown 1827104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 19e5c89e4eSSatish Balay #include <signal.h> 20e5c89e4eSSatish Balay 21670f3ff9SJed Brown struct PetscFPTrapLink { 22670f3ff9SJed Brown PetscFPTrap trapmode; 23670f3ff9SJed Brown struct PetscFPTrapLink *next; 24670f3ff9SJed Brown }; 25aba4c478SBarry Smith static PetscFPTrap _trapmode = PETSC_FP_TRAP_OFF; /* Current trapping mode; see PetscDetermineInitialFPTrap() */ 26670f3ff9SJed Brown static struct PetscFPTrapLink *_trapstack; /* Any pushed states of _trapmode */ 27670f3ff9SJed Brown 28670f3ff9SJed Brown /*@ 29811af0c4SBarry Smith PetscFPTrapPush - push a floating point trapping mode, restored using `PetscFPTrapPop()` 30670f3ff9SJed Brown 31670f3ff9SJed Brown Not Collective 32670f3ff9SJed Brown 334165533cSJose E. Roman Input Parameter: 34811af0c4SBarry Smith . trap - `PETSC_FP_TRAP_ON` or `PETSC_FP_TRAP_OFF` or any of the values passable to `PetscSetFPTrap()` 35670f3ff9SJed Brown 36670f3ff9SJed Brown Level: advanced 37670f3ff9SJed Brown 38cc9df77eSBarry Smith Notes: 39cc9df77eSBarry Smith This only changes the trapping if the new mode is different than the current mode. 40cc9df77eSBarry Smith 41cc9df77eSBarry Smith This routine is called to turn off trapping for certain LAPACK routines that assume that dividing 42cc9df77eSBarry Smith by zero is acceptable. In particular the routine ieeeck(). 43cc9df77eSBarry Smith 44cc9df77eSBarry Smith Most systems by default have all trapping turned off, but certain Fortran compilers have 45cc9df77eSBarry Smith link flags that turn on trapping before the program begins. 46cc9df77eSBarry Smith $ gfortran -ffpe-trap=invalid,zero,overflow,underflow,denormal 47cc9df77eSBarry Smith $ ifort -fpe0 48cc9df77eSBarry Smith 49db781477SPatrick Sanan .seealso: `PetscFPTrapPop()`, `PetscSetFPTrap()`, `PetscDetermineInitialFPTrap()` 50670f3ff9SJed Brown @*/ 51d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPTrapPush(PetscFPTrap trap) 52d71ae5a4SJacob Faibussowitsch { 53670f3ff9SJed Brown struct PetscFPTrapLink *link; 54670f3ff9SJed Brown 55670f3ff9SJed Brown PetscFunctionBegin; 569566063dSJacob Faibussowitsch PetscCall(PetscNew(&link)); 571f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP) 581f006be4SPierre Jolivet #pragma omp critical 591f006be4SPierre Jolivet #endif 601f006be4SPierre Jolivet { 61670f3ff9SJed Brown link->trapmode = _trapmode; 62670f3ff9SJed Brown link->next = _trapstack; 63670f3ff9SJed Brown _trapstack = link; 641f006be4SPierre Jolivet } 659566063dSJacob Faibussowitsch if (trap != _trapmode) PetscCall(PetscSetFPTrap(trap)); 66670f3ff9SJed Brown PetscFunctionReturn(0); 67670f3ff9SJed Brown } 68670f3ff9SJed Brown 69670f3ff9SJed Brown /*@ 70811af0c4SBarry Smith PetscFPTrapPop - push a floating point trapping mode, to be restored using `PetscFPTrapPop()` 71670f3ff9SJed Brown 72670f3ff9SJed Brown Not Collective 73670f3ff9SJed Brown 74670f3ff9SJed Brown Level: advanced 75670f3ff9SJed Brown 76db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscSetFPTrap()`, `PetscDetermineInitialFPTrap()` 77670f3ff9SJed Brown @*/ 78d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFPTrapPop(void) 79d71ae5a4SJacob Faibussowitsch { 80670f3ff9SJed Brown struct PetscFPTrapLink *link; 81670f3ff9SJed Brown 82670f3ff9SJed Brown PetscFunctionBegin; 839566063dSJacob Faibussowitsch if (_trapstack->trapmode != _trapmode) PetscCall(PetscSetFPTrap(_trapstack->trapmode)); 841f006be4SPierre Jolivet #if defined(PETSC_HAVE_THREADSAFETY) && defined(PETSC_HAVE_OPENMP) 851f006be4SPierre Jolivet #pragma omp critical 861f006be4SPierre Jolivet #endif 871f006be4SPierre Jolivet { 88670f3ff9SJed Brown link = _trapstack; 89670f3ff9SJed Brown _trapstack = _trapstack->next; 901f006be4SPierre Jolivet } 919566063dSJacob Faibussowitsch PetscCall(PetscFree(link)); 92670f3ff9SJed Brown PetscFunctionReturn(0); 93670f3ff9SJed Brown } 94670f3ff9SJed Brown 95e5c89e4eSSatish Balay /*--------------------------------------- ---------------------------------------------------*/ 96e5c89e4eSSatish Balay #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP) 97e5c89e4eSSatish Balay #include <floatingpoint.h> 98e5c89e4eSSatish Balay 998cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_flags(char *, char *, char *, char **); 1008cc058d9SJed Brown PETSC_EXTERN PetscErrorCode ieee_handler(char *, char *, sigfpe_handler_type(int, int, struct sigcontext *, char *)); 101e5c89e4eSSatish Balay 1029371c9d4SSatish Balay static struct { 1039371c9d4SSatish Balay int code_no; 1049371c9d4SSatish Balay char *name; 1059371c9d4SSatish Balay } error_codes[] = { 106e5c89e4eSSatish Balay {FPE_INTDIV_TRAP, "integer divide" }, 107e5c89e4eSSatish Balay {FPE_FLTOPERR_TRAP, "IEEE operand error" }, 108e5c89e4eSSatish Balay {FPE_FLTOVF_TRAP, "floating point overflow" }, 109e5c89e4eSSatish Balay {FPE_FLTUND_TRAP, "floating point underflow" }, 110e5c89e4eSSatish Balay {FPE_FLTDIV_TRAP, "floating pointing divide" }, 111e5c89e4eSSatish Balay {FPE_FLTINEX_TRAP, "inexact floating point result"}, 112e5c89e4eSSatish Balay {0, "unknown error" } 113e5c89e4eSSatish Balay }; 114e5c89e4eSSatish Balay #define SIGPC(scp) (scp->sc_pc) 115e5c89e4eSSatish Balay 116cf0818bdSBarry Smith /* this function gets called if a trap has occurred and been caught */ 117d71ae5a4SJacob Faibussowitsch sigfpe_handler_type PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp, char *addr) 118d71ae5a4SJacob Faibussowitsch { 1195f80ce2aSJacob Faibussowitsch int err_ind = -1; 120e5c89e4eSSatish Balay 121e5c89e4eSSatish Balay PetscFunctionBegin; 1225f80ce2aSJacob Faibussowitsch for (int j = 0; error_codes[j].code_no; j++) { 123e5c89e4eSSatish Balay if (error_codes[j].code_no == code) err_ind = j; 124e5c89e4eSSatish Balay } 125e5c89e4eSSatish Balay 126a297a907SKarl Rupp if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp)); 127a297a907SKarl Rupp else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp)); 128a297a907SKarl Rupp 12949c86fc7SBarry Smith (void)PetscError(PETSC_COMM_SELF, PETSC_ERR_FP, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 13041e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 131e5c89e4eSSatish Balay PetscFunctionReturn(0); 132e5c89e4eSSatish Balay } 133e5c89e4eSSatish Balay 134e30d2299SSatish Balay /*@ 135cf0818bdSBarry Smith PetscSetFPTrap - Enables traps/exceptions on common floating point errors. This option may not work on certain systems or only a 136cf0818bdSBarry Smith subset of exceptions may be trapable. 137e5c89e4eSSatish Balay 138e5c89e4eSSatish Balay Not Collective 139e5c89e4eSSatish Balay 140e5c89e4eSSatish Balay Input Parameters: 141cf0818bdSBarry Smith . flag - values are 142cf0818bdSBarry Smith .vb 143cf0818bdSBarry Smith PETSC_FP_TRAP_OFF - do not trap any exceptions 144cf0818bdSBarry Smith PETSC_FP_TRAP_ON - all exceptions that are possible on the system except underflow 145cf0818bdSBarry Smith PETSC_FP_TRAP_INDIV - integer divide by zero 146cf0818bdSBarry Smith PETSC_FP_TRAP_FLTOPERR - improper argument to function, for example with real numbers, the square root of a negative number 147cf0818bdSBarry Smith PETSC_FP_TRAP_FLTOVF - overflow 148cf0818bdSBarry Smith PETSC_FP_TRAP_FLTUND - underflow - not trapped by default on most systems 149cf0818bdSBarry Smith PETSC_FP_TRAP_FLTDIV - floating point divide by zero 150cf0818bdSBarry Smith PETSC_FP_TRAP_FLTINEX - inexact floating point result 151cf0818bdSBarry Smith .ve 152e5c89e4eSSatish Balay 153e5c89e4eSSatish Balay Options Database Keys: 154cf0818bdSBarry Smith . -fp_trap <off,on> - turn on or off trapping of floating point exceptions 155e5c89e4eSSatish Balay 156e5c89e4eSSatish Balay Level: advanced 157e5c89e4eSSatish Balay 158cf0818bdSBarry Smith Notes: 159811af0c4SBarry Smith Currently only `PETSC_FP_TRAP_OFF` and `PETSC_FP_TRAP_ON` are handled. All others are treated as `PETSC_FP_TRAP_ON`. 160cf0818bdSBarry Smith 161cf0818bdSBarry Smith The values are bit values and may be |ed together in the function call 162cf0818bdSBarry Smith 163cf0818bdSBarry Smith On systems that support it this routine causes floating point 164cf0818bdSBarry Smith overflow, divide-by-zero, and invalid-operand (e.g., a NaN), but not underflow, to 165e5c89e4eSSatish Balay cause a message to be printed and the program to exit. 166e5c89e4eSSatish Balay 167cc9df77eSBarry Smith On many common systems, the floating 1687d125cddSJed Brown point exception state is not preserved from the location where the trap 1697d125cddSJed Brown occurred through to the signal handler. In this case, the signal handler 1707d125cddSJed Brown will just say that an unknown floating point exception occurred and which 1717d125cddSJed Brown function it occurred in. If you run with -fp_trap in a debugger, it will 172cc9df77eSBarry Smith break on the line where the error occurred. On systems that support C99 173cc9df77eSBarry Smith floating point exception handling You can check which 1747d125cddSJed Brown exception occurred using fetestexcept(FE_ALL_EXCEPT). See fenv.h 1757d125cddSJed Brown (usually at /usr/include/bits/fenv.h) for the enum values on your system. 1767d125cddSJed Brown 177db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscFPTrapPop()`, `PetscDetermineInitialFPTrap()` 178e5c89e4eSSatish Balay @*/ 179d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 180d71ae5a4SJacob Faibussowitsch { 181e5c89e4eSSatish Balay char *out; 182e5c89e4eSSatish Balay 183e5c89e4eSSatish Balay PetscFunctionBegin; 184e5c89e4eSSatish Balay /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */ 185e5c89e4eSSatish Balay (void)ieee_flags("clear", "exception", "all", &out); 186bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) { 187e5c89e4eSSatish Balay /* 188a297a907SKarl Rupp To trap more fp exceptions, including underflow, change the line below to 189e5c89e4eSSatish Balay if (ieee_handler("set","all",PetscDefaultFPTrap)) { 190e5c89e4eSSatish Balay */ 191a297a907SKarl Rupp if (ieee_handler("set", "common", PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n"); 192a297a907SKarl Rupp } else if (ieee_handler("clear", "common", PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 193a297a907SKarl Rupp 194670f3ff9SJed Brown _trapmode = flag; 195bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_SUN4_STYLE_FPTRAP\n")); 196e5c89e4eSSatish Balay PetscFunctionReturn(0); 197e5c89e4eSSatish Balay } 198e5c89e4eSSatish Balay 199cc9df77eSBarry Smith /*@ 200811af0c4SBarry Smith PetscDetermineInitialFPTrap - Attempts to determine the floating point trapping that exists when `PetscInitialize()` is called 201cc9df77eSBarry Smith 202cc9df77eSBarry Smith Not Collective 203cc9df77eSBarry Smith 204811af0c4SBarry Smith Note: 205cc9df77eSBarry Smith Currently only supported on Linux and MacOS. Checks if divide by zero is enable and if so declares that trapping is on. 206cc9df77eSBarry Smith 207ee300463SSatish Balay Level: advanced 208cc9df77eSBarry Smith 209db781477SPatrick Sanan .seealso: `PetscFPTrapPush()`, `PetscFPTrapPop()`, `PetscDetermineInitialFPTrap()` 210cc9df77eSBarry Smith @*/ 211d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 212d71ae5a4SJacob Faibussowitsch { 213cc9df77eSBarry Smith PetscFunctionBegin; 2149566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 215cc9df77eSBarry Smith PetscFunctionReturn(0); 216cc9df77eSBarry Smith } 217cc9df77eSBarry Smith 218e5c89e4eSSatish Balay /* -------------------------------------------------------------------------------------------*/ 219e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP) 220e5c89e4eSSatish Balay #include <sunmath.h> 221e5c89e4eSSatish Balay #include <floatingpoint.h> 222e5c89e4eSSatish Balay #include <siginfo.h> 223e5c89e4eSSatish Balay #include <ucontext.h> 224e5c89e4eSSatish Balay 2259371c9d4SSatish Balay static struct { 2269371c9d4SSatish Balay int code_no; 2279371c9d4SSatish Balay char *name; 2289371c9d4SSatish Balay } error_codes[] = { 229e5c89e4eSSatish Balay {FPE_FLTINV, "invalid floating point operand"}, 230e5c89e4eSSatish Balay {FPE_FLTRES, "inexact floating point result" }, 231e5c89e4eSSatish Balay {FPE_FLTDIV, "division-by-zero" }, 232e5c89e4eSSatish Balay {FPE_FLTUND, "floating point underflow" }, 233e5c89e4eSSatish Balay {FPE_FLTOVF, "floating point overflow" }, 234e5c89e4eSSatish Balay {0, "unknown error" } 235e5c89e4eSSatish Balay }; 236e5c89e4eSSatish Balay #define SIGPC(scp) (scp->si_addr) 237e5c89e4eSSatish Balay 238d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig, siginfo_t *scp, ucontext_t *uap) 239d71ae5a4SJacob Faibussowitsch { 2405f80ce2aSJacob Faibussowitsch int err_ind = -1, code = scp->si_code; 241e5c89e4eSSatish Balay 242e5c89e4eSSatish Balay PetscFunctionBegin; 2435f80ce2aSJacob Faibussowitsch for (int j = 0; error_codes[j].code_no; j++) { 244e5c89e4eSSatish Balay if (error_codes[j].code_no == code) err_ind = j; 245e5c89e4eSSatish Balay } 246e5c89e4eSSatish Balay 247a297a907SKarl Rupp if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n", error_codes[err_ind].name, SIGPC(scp)); 248a297a907SKarl Rupp else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n", code, SIGPC(scp)); 249a297a907SKarl Rupp 25049c86fc7SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 25141e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 252e5c89e4eSSatish Balay } 253e5c89e4eSSatish Balay 254d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 255d71ae5a4SJacob Faibussowitsch { 256e5c89e4eSSatish Balay char *out; 257e5c89e4eSSatish Balay 258e5c89e4eSSatish Balay PetscFunctionBegin; 259e5c89e4eSSatish Balay /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */ 260e5c89e4eSSatish Balay (void)ieee_flags("clear", "exception", "all", &out); 261e5c89e4eSSatish Balay if (flag == PETSC_FP_TRAP_ON) { 262a297a907SKarl Rupp if (ieee_handler("set", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n"); 263cc9df77eSBarry Smith } else { 264cc9df77eSBarry Smith if (ieee_handler("clear", "common", (sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 265cc9df77eSBarry Smith } 266670f3ff9SJed Brown _trapmode = flag; 267bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL,"Using PETSC_HAVE_SOLARIS_STYLE_FPTRAP\n"); 268e5c89e4eSSatish Balay PetscFunctionReturn(0); 269e5c89e4eSSatish Balay } 270e5c89e4eSSatish Balay 271d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 272d71ae5a4SJacob Faibussowitsch { 273cc9df77eSBarry Smith PetscFunctionBegin; 2749566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 275cc9df77eSBarry Smith PetscFunctionReturn(0); 276cc9df77eSBarry Smith } 277cc9df77eSBarry Smith 278cc9df77eSBarry Smith /* ------------------------------------------------------------------------------------------*/ 279e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_IRIX_STYLE_FPTRAP) 280e5c89e4eSSatish Balay #include <sigfpe.h> 2819371c9d4SSatish Balay static struct { 2829371c9d4SSatish Balay int code_no; 2839371c9d4SSatish Balay char *name; 2849371c9d4SSatish Balay } error_codes[] = { 285e5c89e4eSSatish Balay {_INVALID, "IEEE operand error" }, 286e5c89e4eSSatish Balay {_OVERFL, "floating point overflow" }, 287e5c89e4eSSatish Balay {_UNDERFL, "floating point underflow"}, 288e5c89e4eSSatish Balay {_DIVZERO, "floating point divide" }, 289e5c89e4eSSatish Balay {0, "unknown error" } 290e5c89e4eSSatish Balay }; 291d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(unsigned exception[], int val[]) 292d71ae5a4SJacob Faibussowitsch { 2935f80ce2aSJacob Faibussowitsch int err_ind = -1, code = exception[0]; 294e5c89e4eSSatish Balay 295e5c89e4eSSatish Balay PetscFunctionBegin; 2965f80ce2aSJacob Faibussowitsch for (int j = 0; error_codes[j].code_no; j++) { 297e5c89e4eSSatish Balay if (error_codes[j].code_no == code) err_ind = j; 298e5c89e4eSSatish Balay } 299a297a907SKarl Rupp if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name); 300a297a907SKarl Rupp else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", code); 301a297a907SKarl Rupp 30249c86fc7SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 30341e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 304e5c89e4eSSatish Balay } 305e5c89e4eSSatish Balay 306d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 307d71ae5a4SJacob Faibussowitsch { 308e5c89e4eSSatish Balay PetscFunctionBegin; 309bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) handle_sigfpes(_ON, , _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, PetscDefaultFPTrap, _ABORT_ON_ERROR, 0); 310cc9df77eSBarry Smith else handle_sigfpes(_OFF, _EN_UNDERFL | _EN_OVERFL | _EN_DIVZERO | _EN_INVALID, 0, _ABORT_ON_ERROR, 0); 311670f3ff9SJed Brown _trapmode = flag; 312bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IRIX_STYLE_FPTRAP\n")); 313cc9df77eSBarry Smith PetscFunctionReturn(0); 314cc9df77eSBarry Smith } 315cc9df77eSBarry Smith 316d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 317d71ae5a4SJacob Faibussowitsch { 318cc9df77eSBarry Smith PetscFunctionBegin; 3199566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 320cc9df77eSBarry Smith PetscFunctionReturn(0); 321cc9df77eSBarry Smith } 322cc9df77eSBarry Smith 323cc9df77eSBarry Smith /*----------------------------------------------- --------------------------------------------*/ 324cc9df77eSBarry Smith #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP) 325e5c89e4eSSatish Balay /* In "fast" mode, floating point traps are imprecise and ignored. 326e5c89e4eSSatish Balay This is the reason for the fptrap(FP_TRAP_SYNC) call */ 327e5c89e4eSSatish Balay struct sigcontext; 328e5c89e4eSSatish Balay #include <fpxcp.h> 329e5c89e4eSSatish Balay #include <fptrap.h> 330e5c89e4eSSatish Balay #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000) 331e5c89e4eSSatish Balay #define FPE_FLTOVF_TRAP (fptrap_t)(0x10000000) 332e5c89e4eSSatish Balay #define FPE_FLTUND_TRAP (fptrap_t)(0x08000000) 333e5c89e4eSSatish Balay #define FPE_FLTDIV_TRAP (fptrap_t)(0x04000000) 334e5c89e4eSSatish Balay #define FPE_FLTINEX_TRAP (fptrap_t)(0x02000000) 335e5c89e4eSSatish Balay 3369371c9d4SSatish Balay static struct { 3379371c9d4SSatish Balay int code_no; 3389371c9d4SSatish Balay char *name; 3399371c9d4SSatish Balay } error_codes[] = { 340e5c89e4eSSatish Balay {FPE_FLTOPERR_TRAP, "IEEE operand error" }, 341e5c89e4eSSatish Balay {FPE_FLTOVF_TRAP, "floating point overflow" }, 342e5c89e4eSSatish Balay {FPE_FLTUND_TRAP, "floating point underflow" }, 343e5c89e4eSSatish Balay {FPE_FLTDIV_TRAP, "floating point divide" }, 344e5c89e4eSSatish Balay {FPE_FLTINEX_TRAP, "inexact floating point result"}, 345bd2b07b1SBarry Smith < {0, "unknown error" } 346e5c89e4eSSatish Balay }; 347e5c89e4eSSatish Balay #define SIGPC(scp) (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */ 348e5c89e4eSSatish Balay /* 349e5c89e4eSSatish Balay For some reason, scp->sc_jmpbuf does not work on the RS6000, even though 350e5c89e4eSSatish Balay it looks like it should from the include definitions. It is probably 351e5c89e4eSSatish Balay some strange interaction with the "POSIX_SOURCE" that we require. 352e5c89e4eSSatish Balay */ 353e5c89e4eSSatish Balay 354d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig, int code, struct sigcontext *scp) 355d71ae5a4SJacob Faibussowitsch { 356e5c89e4eSSatish Balay int err_ind, j; 357e5c89e4eSSatish Balay fp_ctx_t flt_context; 358e5c89e4eSSatish Balay 359e5c89e4eSSatish Balay PetscFunctionBegin; 360e5c89e4eSSatish Balay fp_sh_trap_info(scp, &flt_context); 361e5c89e4eSSatish Balay 362e5c89e4eSSatish Balay err_ind = -1; 363e5c89e4eSSatish Balay for (j = 0; error_codes[j].code_no; j++) { 364e5c89e4eSSatish Balay if (error_codes[j].code_no == flt_context.trap) err_ind = j; 365e5c89e4eSSatish Balay } 366e5c89e4eSSatish Balay 367a297a907SKarl Rupp if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n", error_codes[err_ind].name); 368a297a907SKarl Rupp else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n", flt_context.trap); 369a297a907SKarl Rupp 37049c86fc7SBarry Smith (void)PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 37141e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 372e5c89e4eSSatish Balay } 373e5c89e4eSSatish Balay 374d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 375d71ae5a4SJacob Faibussowitsch { 376e5c89e4eSSatish Balay PetscFunctionBegin; 377bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) { 378e5c89e4eSSatish Balay signal(SIGFPE, (void (*)(int))PetscDefaultFPTrap); 379e5c89e4eSSatish Balay fp_trap(FP_TRAP_SYNC); 380bd2b07b1SBarry Smith /* fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); */ 381bd2b07b1SBarry Smith fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW); 382e5c89e4eSSatish Balay } else { 383e5c89e4eSSatish Balay signal(SIGFPE, SIG_DFL); 384cc9df77eSBarry Smith fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW); 385e5c89e4eSSatish Balay fp_trap(FP_TRAP_OFF); 386e5c89e4eSSatish Balay } 387cf0818bdSBarry Smith _trapmode = flag; 388bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_RS6000_STYLE_FPTRAP\n")); 389e5c89e4eSSatish Balay PetscFunctionReturn(0); 390e5c89e4eSSatish Balay } 391e5c89e4eSSatish Balay 392d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 393d71ae5a4SJacob Faibussowitsch { 394cc9df77eSBarry Smith PetscFunctionBegin; 3959566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 396cc9df77eSBarry Smith PetscFunctionReturn(0); 397cc9df77eSBarry Smith } 398cc9df77eSBarry Smith 399cc9df77eSBarry Smith /* ------------------------------------------------------------*/ 400cc9df77eSBarry Smith #elif defined(PETSC_HAVE_WINDOWS_COMPILERS) 401cc9df77eSBarry Smith #include <float.h> 402d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig) 403d71ae5a4SJacob Faibussowitsch { 404cc9df77eSBarry Smith PetscFunctionBegin; 405cc9df77eSBarry Smith (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 40649c86fc7SBarry Smith PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 407cc9df77eSBarry Smith PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 408cc9df77eSBarry Smith } 409cc9df77eSBarry Smith 410d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 411d71ae5a4SJacob Faibussowitsch { 412cc9df77eSBarry Smith unsigned int cw; 413cc9df77eSBarry Smith 414cc9df77eSBarry Smith PetscFunctionBegin; 415bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) { 416bd2b07b1SBarry Smith /* cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW; */ 417bd2b07b1SBarry Smith cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW; 41808401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler"); 419cc9df77eSBarry Smith } else { 420cc9df77eSBarry Smith cw = 0; 42108401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler"); 422cc9df77eSBarry Smith } 423cc9df77eSBarry Smith (void)_controlfp(0, cw); 424cf0818bdSBarry Smith _trapmode = flag; 425bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_WINDOWS_COMPILERS FPTRAP\n")); 426cc9df77eSBarry Smith PetscFunctionReturn(0); 427cc9df77eSBarry Smith } 428cc9df77eSBarry Smith 429d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 430d71ae5a4SJacob Faibussowitsch { 431cc9df77eSBarry Smith PetscFunctionBegin; 4329566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 433cc9df77eSBarry Smith PetscFunctionReturn(0); 434cc9df77eSBarry Smith } 435cc9df77eSBarry Smith 436cc9df77eSBarry Smith /* ------------------------------------------------------------*/ 4379a2402e9SBarry Smith #elif defined(PETSC_HAVE_FENV_H) && !defined(__cplusplus) 438b014e56cSJed Brown /* 439b014e56cSJed Brown C99 style floating point environment. 440b014e56cSJed Brown 441b014e56cSJed Brown Note that C99 merely specifies how to save, restore, and clear the floating 442b014e56cSJed Brown point environment as well as defining an enumeration of exception codes. In 443b014e56cSJed Brown particular, C99 does not specify how to make floating point exceptions raise 444b014e56cSJed Brown a signal. Glibc offers this capability through FE_NOMASK_ENV (or with finer 445b014e56cSJed Brown granularity, feenableexcept()), xmmintrin.h offers _MM_SET_EXCEPTION_MASK(). 446b014e56cSJed Brown */ 447b014e56cSJed Brown #include <fenv.h> 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; 482b014e56cSJed Brown (*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 */ 487b014e56cSJed Brown (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n"); 4887d125cddSJed Brown (*PetscErrorPrintf)("The specific exception can be determined by running in a debugger. When the\n"); 4897d125cddSJed Brown (*PetscErrorPrintf)("debugger traps the signal, the exception can be found with fetestexcept(0x%x)\n", FE_ALL_EXCEPT); 4907d125cddSJed Brown (*PetscErrorPrintf)("where the result is a bitwise OR of the following flags:\n"); 4917d125cddSJed Brown (*PetscErrorPrintf)("FE_INVALID=0x%x FE_DIVBYZERO=0x%x FE_OVERFLOW=0x%x FE_UNDERFLOW=0x%x FE_INEXACT=0x%x\n", FE_INVALID, FE_DIVBYZERO, FE_OVERFLOW, FE_UNDERFLOW, FE_INEXACT); 492b014e56cSJed Brown } 493accbd18bSBarry Smith #else 494accbd18bSBarry Smith (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n"); 495accbd18bSBarry Smith #endif 4967d125cddSJed Brown 4977d125cddSJed Brown (*PetscErrorPrintf)("Try option -start_in_debugger\n"); 49827104ee2SJacob Faibussowitsch #if PetscDefined(USE_DEBUG) 499*dfb7d7afSStefano Zampini #if !PetscDefined(HAVE_THREADSAFETY) 5007d125cddSJed Brown (*PetscErrorPrintf)("likely location of problem given in stack below\n"); 5017d125cddSJed Brown (*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n"); 502639ff905SBarry Smith PetscStackView(PETSC_STDOUT); 503*dfb7d7afSStefano Zampini #endif 50427104ee2SJacob Faibussowitsch #else 5057d125cddSJed Brown (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n"); 5067d125cddSJed Brown (*PetscErrorPrintf)("with -start_in_debugger to get more information on the crash.\n"); 50727104ee2SJacob Faibussowitsch #endif 50849c86fc7SBarry Smith 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; 541b014e56cSJed Brown PetscFunctionReturn(0); 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")); 559cc9df77eSBarry Smith PetscFunctionReturn(0); 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 } 568cc9df77eSBarry Smith PetscFunctionReturn(0); 569cc9df77eSBarry Smith #endif 570cc9df77eSBarry Smith } 571cc9df77eSBarry Smith 572cc9df77eSBarry Smith /* ------------------------------------------------------------*/ 573cc9df77eSBarry Smith #elif defined(PETSC_HAVE_IEEEFP_H) 574cc9df77eSBarry Smith #include <ieeefp.h> 575d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig) 576d71ae5a4SJacob Faibussowitsch { 577cc9df77eSBarry Smith PetscFunctionBegin; 578cc9df77eSBarry Smith (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 57949c86fc7SBarry Smith PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 580cc9df77eSBarry Smith PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 581cc9df77eSBarry Smith } 582cc9df77eSBarry Smith 583d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 584d71ae5a4SJacob Faibussowitsch { 585cc9df77eSBarry Smith PetscFunctionBegin; 586cf0818bdSBarry Smith if (flag == PETSC_FP_TRAP_ON) { 587cc9df77eSBarry Smith #if defined(PETSC_HAVE_FPPRESETSTICKY) 588cc9df77eSBarry Smith fpresetsticky(fpgetsticky()); 589cc9df77eSBarry Smith #elif defined(PETSC_HAVE_FPSETSTICKY) 590cc9df77eSBarry Smith fpsetsticky(fpgetsticky()); 591cc9df77eSBarry Smith #endif 592cc9df77eSBarry Smith fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_OFL); 59308401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, PetscDefaultFPTrap), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't set floating point handler"); 594cc9df77eSBarry Smith } else { 595cc9df77eSBarry Smith #if defined(PETSC_HAVE_FPPRESETSTICKY) 596cc9df77eSBarry Smith fpresetsticky(fpgetsticky()); 597cc9df77eSBarry Smith #elif defined(PETSC_HAVE_FPSETSTICKY) 598cc9df77eSBarry Smith fpsetsticky(fpgetsticky()); 599cc9df77eSBarry Smith #endif 600cc9df77eSBarry Smith fpsetmask(0); 60108401ef6SPierre Jolivet PetscCheck(SIG_ERR != signal(SIGFPE, SIG_DFL), PETSC_COMM_SELF, PETSC_ERR_LIB, "Can't clear floating point handler"); 602cc9df77eSBarry Smith } 603cf0818bdSBarry Smith _trapmode = flag; 604bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using PETSC_HAVE_IEEEFP_H FPTRAP\n")); 605cc9df77eSBarry Smith PetscFunctionReturn(0); 606cc9df77eSBarry Smith } 607cc9df77eSBarry Smith 608d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 609d71ae5a4SJacob Faibussowitsch { 610cc9df77eSBarry Smith PetscFunctionBegin; 6119566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 612cc9df77eSBarry Smith PetscFunctionReturn(0); 613cc9df77eSBarry Smith } 614cc9df77eSBarry Smith 615e5c89e4eSSatish Balay /* -------------------------Default -----------------------------------*/ 616e5c89e4eSSatish Balay #else 61799e0435eSBarry Smith 618d71ae5a4SJacob Faibussowitsch void PetscDefaultFPTrap(int sig) 619d71ae5a4SJacob Faibussowitsch { 620e5c89e4eSSatish Balay PetscFunctionBegin; 621e5c89e4eSSatish Balay (*PetscErrorPrintf)("*** floating point error occurred ***\n"); 62249c86fc7SBarry Smith PetscError(PETSC_COMM_SELF, 0, NULL, NULL, PETSC_ERR_FP, PETSC_ERROR_REPEAT, "floating point error"); 62341e02c4dSJunchao Zhang PETSCABORT(MPI_COMM_WORLD, PETSC_ERR_FP); 624e5c89e4eSSatish Balay } 62599e0435eSBarry Smith 626d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetFPTrap(PetscFPTrap flag) 627d71ae5a4SJacob Faibussowitsch { 628e5c89e4eSSatish Balay PetscFunctionBegin; 629bd2b07b1SBarry Smith if (flag == PETSC_FP_TRAP_ON) { 630a297a907SKarl Rupp if (SIG_ERR == signal(SIGFPE, PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n"); 631a297a907SKarl Rupp } else if (SIG_ERR == signal(SIGFPE, SIG_DFL)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n"); 632a297a907SKarl Rupp 633cf0818bdSBarry Smith _trapmode = flag; 634bd2b07b1SBarry Smith PetscCall(PetscInfo(NULL, "Using default FPTRAP\n")); 635e5c89e4eSSatish Balay PetscFunctionReturn(0); 636e5c89e4eSSatish Balay } 637cc9df77eSBarry Smith 638d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDetermineInitialFPTrap(void) 639d71ae5a4SJacob Faibussowitsch { 640cc9df77eSBarry Smith PetscFunctionBegin; 6419566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Unable to determine initial floating point trapping. Assuming it is off\n")); 642cc9df77eSBarry Smith PetscFunctionReturn(0); 643cc9df77eSBarry Smith } 644e5c89e4eSSatish Balay #endif 645