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