Actual source code: fp.c
1: #define PETSC_DLL
2: /*
3: * IEEE error handler for all machines. Since each machine has
4: * enough slight differences we have completely separate codes for each one.
5: *
6: */
7: #include petsc.h
8: #include petscsys.h
9: #include <signal.h>
10: #if defined(PETSC_HAVE_STDLIB_H)
11: #include <stdlib.h>
12: #endif
13: #include "petscfix.h"
16: /*--------------------------------------- ---------------------------------------------------*/
17: #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP)
18: #include <floatingpoint.h>
21: PetscErrorCode ieee_flags(char*,char*,char*,char**);
22: PetscErrorCode ieee_handler(char *,char *,sigfpe_handler_type(int,int,struct sigcontext*,char *));
25: struct { int code_no; char *name; } error_codes[] = {
26: { FPE_INTDIV_TRAP ,"integer divide" },
27: { FPE_FLTOPERR_TRAP ,"IEEE operand error" },
28: { FPE_FLTOVF_TRAP ,"floating point overflow" },
29: { FPE_FLTUND_TRAP ,"floating point underflow" },
30: { FPE_FLTDIV_TRAP ,"floating pointing divide" },
31: { FPE_FLTINEX_TRAP ,"inexact floating point result" },
32: { 0 ,"unknown error" }
33: } ;
34: #define SIGPC(scp) (scp->sc_pc)
38: sigfpe_handler_type PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp,char *addr)
39: {
41: int err_ind = -1,j;
44: for (j = 0 ; error_codes[j].code_no ; j++) {
45: if (error_codes[j].code_no == code) err_ind = j;
46: }
48: if (err_ind >= 0) {
49: (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp));
50: } else {
51: (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp));
52: }
53: PetscError(PETSC_ERR_FP,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
54: MPI_Abort(PETSC_COMM_WORLD,0);
55: return(0);
56: }
60: /*@C
61: PetscSetFPTrap - Enables traps/exceptions on common floating point errors.
62: This option may not work on certain machines.
64: Not Collective
66: Input Parameters:
67: . flag - PETSC_FP_TRAP_ON, PETSC_FP_TRAP_OFF.
69: Options Database Keys:
70: . -fp_trap - Activates floating point trapping
72: Level: advanced
74: Description:
75: On systems that support it, this routine causes floating point
76: overflow, divide-by-zero, and invalid-operand (e.g., a NaN) to
77: cause a message to be printed and the program to exit.
79: Caution:
80: On certain machines, in particular the IBM rs6000, floating point
81: trapping is VERY slow!
83: Concepts: floating point exceptions^trapping
84: Concepts: divide by zero
86: @*/
87: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
88: {
89: char *out;
92: /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */
93: (void) ieee_flags("clear","exception","all",&out);
94: if (flag == PETSC_FP_TRAP_ON) {
95: if (ieee_handler("set","common",PetscDefaultFPTrap)) {
96: /*
97: To trap more fp exceptions, including undrflow, change the above line to
98: if (ieee_handler("set","all",PetscDefaultFPTrap)) {
99: */
100: (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
101: }
102: } else {
103: if (ieee_handler("clear","common",PetscDefaultFPTrap)) {
104: (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
105: }
106: }
107: return(0);
108: }
110: /* -------------------------------------------------------------------------------------------*/
111: #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP)
112: #include <sunmath.h>
113: #include <floatingpoint.h>
114: #include <siginfo.h>
115: #include <ucontext.h>
117: struct { int code_no; char *name; } error_codes[] = {
118: { FPE_FLTINV,"invalid floating point operand"},
119: { FPE_FLTRES,"inexact floating point result"},
120: { FPE_FLTDIV,"division-by-zero"},
121: { FPE_FLTUND,"floating point underflow"},
122: { FPE_FLTOVF,"floating point overflow"},
123: { 0, "unknown error"}
124: };
125: #define SIGPC(scp) (scp->si_addr)
129: void PetscDefaultFPTrap(int sig,siginfo_t *scp,ucontext_t *uap)
130: {
131: int err_ind,j,code = scp->si_code;
135: err_ind = -1 ;
136: for (j = 0 ; error_codes[j].code_no ; j++) {
137: if (error_codes[j].code_no == code) err_ind = j;
138: }
140: if (err_ind >= 0) {
141: (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp));
142: } else {
143: (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp));
144: }
145: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
146: MPI_Abort(PETSC_COMM_WORLD,0);
147: }
151: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
152: {
153: char *out;
156: /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */
157: (void) ieee_flags("clear","exception","all",&out);
158: if (flag == PETSC_FP_TRAP_ON) {
159: if (ieee_handler("set","common",(sigfpe_handler_type)PetscDefaultFPTrap)) {
160: (*PetscErrorPrintf)("Can't set floating point handler\n");
161: }
162: } else {
163: if (ieee_handler("clear","common",(sigfpe_handler_type)PetscDefaultFPTrap)) {
164: (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
165: }
166: }
167: return(0);
168: }
170: /* ------------------------------------------------------------------------------------------*/
172: #elif defined (PETSC_HAVE_IRIX_STYLE_FPTRAP)
173: #include <sigfpe.h>
174: struct { int code_no; char *name; } error_codes[] = {
175: { _INVALID ,"IEEE operand error" },
176: { _OVERFL ,"floating point overflow" },
177: { _UNDERFL ,"floating point underflow" },
178: { _DIVZERO ,"floating point divide" },
179: { 0 ,"unknown error" }
180: } ;
183: void PetscDefaultFPTrap(unsigned exception[],int val[])
184: {
185: int err_ind,j,code;
188: code = exception[0];
189: err_ind = -1 ;
190: for (j = 0 ; error_codes[j].code_no ; j++){
191: if (error_codes[j].code_no == code) err_ind = j;
192: }
193: if (err_ind >= 0){
194: (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name);
195: } else{
196: (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",code);
197: }
198: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
199: MPI_Abort(PETSC_COMM_WORLD,0);
200: }
204: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
205: {
207: if (flag == PETSC_FP_TRAP_ON) {
208: handle_sigfpes(_ON,_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,PetscDefaultFPTrap,_ABORT_ON_ERROR,0);
209: } else {
210: handle_sigfpes(_OFF,_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,0,_ABORT_ON_ERROR,0);
211: }
212: return(0);
213: }
214: /*----------------------------------------------- --------------------------------------------*/
215: /* In "fast" mode, floating point traps are imprecise and ignored.
216: This is the reason for the fptrap(FP_TRAP_SYNC) call */
217: #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP)
218: struct sigcontext;
219: #include <fpxcp.h>
220: #include <fptrap.h>
221: #include <stdlib.h>
222: #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000)
223: #define FPE_FLTOVF_TRAP (fptrap_t)(0x10000000)
224: #define FPE_FLTUND_TRAP (fptrap_t)(0x08000000)
225: #define FPE_FLTDIV_TRAP (fptrap_t)(0x04000000)
226: #define FPE_FLTINEX_TRAP (fptrap_t)(0x02000000)
228: struct { int code_no; char *name; } error_codes[] = {
229: {FPE_FLTOPERR_TRAP ,"IEEE operand error" },
230: { FPE_FLTOVF_TRAP ,"floating point overflow" },
231: { FPE_FLTUND_TRAP ,"floating point underflow" },
232: { FPE_FLTDIV_TRAP ,"floating point divide" },
233: { FPE_FLTINEX_TRAP ,"inexact floating point result" },
234: { 0 ,"unknown error" }
235: } ;
236: #define SIGPC(scp) (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */
237: /*
238: For some reason, scp->sc_jmpbuf does not work on the RS6000, even though
239: it looks like it should from the include definitions. It is probably
240: some strange interaction with the "POSIX_SOURCE" that we require.
241: */
245: void PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp)
246: {
248: int err_ind,j;
249: fp_ctx_t flt_context;
252: fp_sh_trap_info(scp,&flt_context);
253:
254: err_ind = -1 ;
255: for (j = 0 ; error_codes[j].code_no ; j++) {
256: if (error_codes[j].code_no == flt_context.trap) err_ind = j;
257: }
259: if (err_ind >= 0){
260: (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name);
261: } else{
262: (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",flt_context.trap);
263: }
264: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
265: MPI_Abort(PETSC_COMM_WORLD,0);
266: }
270: PetscErrorCode PetscSetFPTrap(PetscFPTrap on)
271: {
272: int flag;
275: if (on == PETSC_FP_TRAP_ON) {
276: signal(SIGFPE,(void (*)(int))PetscDefaultFPTrap);
277: fp_trap(FP_TRAP_SYNC);
278: fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
279: /* fp_enable(mask) for individual traps. Values are:
280: TRP_INVALID
281: TRP_DIV_BY_ZERO
282: TRP_OVERFLOW
283: TRP_UNDERFLOW
284: TRP_INEXACT
285: Can OR then together.
286: fp_enable_all(); for all traps.
287: */
288: } else {
289: signal(SIGFPE,SIG_DFL);
290: fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
291: fp_trap(FP_TRAP_OFF);
292: }
293: return(0);
294: }
296: /* -------------------------Default -----------------------------------*/
297: #else
298: struct PETSCERRORCODES { int code_no; const char *name; } error_codes[] = {
299: { 0 ,"unknown error" }
300: } ;
304: void PetscDefaultFPTrap(int sig)
305: {
307: (*PetscErrorPrintf)("*** floating point error occurred ***\n");
308: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
309: MPI_Abort(PETSC_COMM_WORLD,0);
310: }
314: PetscErrorCode PETSC_DLLEXPORT PetscSetFPTrap(PetscFPTrap on)
315: {
317: if (on == PETSC_FP_TRAP_ON) {
318: if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) {
319: (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
320: }
321: } else {
322: if (SIG_ERR == signal(SIGFPE,SIG_DFL)) {
323: (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
324: }
325: }
326: return(0);
327: }
328: #endif