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: /*@
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: {
273: if (on == PETSC_FP_TRAP_ON) {
274: signal(SIGFPE,(void (*)(int))PetscDefaultFPTrap);
275: fp_trap(FP_TRAP_SYNC);
276: fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
277: /* fp_enable(mask) for individual traps. Values are:
278: TRP_INVALID
279: TRP_DIV_BY_ZERO
280: TRP_OVERFLOW
281: TRP_UNDERFLOW
282: TRP_INEXACT
283: Can OR then together.
284: fp_enable_all(); for all traps.
285: */
286: } else {
287: signal(SIGFPE,SIG_DFL);
288: fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
289: fp_trap(FP_TRAP_OFF);
290: }
291: return(0);
292: }
294: /* -------------------------Default -----------------------------------*/
295: #else
296: struct PETSCERRORCODES { int code_no; const char *name; } error_codes[] = {
297: { 0 ,"unknown error" }
298: } ;
302: void PetscDefaultFPTrap(int sig)
303: {
305: (*PetscErrorPrintf)("*** floating point error occurred ***\n");
306: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
307: MPI_Abort(PETSC_COMM_WORLD,0);
308: }
312: PetscErrorCode PetscSetFPTrap(PetscFPTrap on)
313: {
315: if (on == PETSC_FP_TRAP_ON) {
316: if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) {
317: (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
318: }
319: } else {
320: if (SIG_ERR == signal(SIGFPE,SIG_DFL)) {
321: (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
322: }
323: }
324: return(0);
325: }
326: #endif