Actual source code: fp.c
1: /*$Id: fp.c,v 1.79 2001/08/15 20:12:54 balay Exp $*/
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>
20: EXTERN_C_BEGIN
21: int ieee_flags(char*,char*,char*,char**);
22: int ieee_handler(char *,char *,sigfpe_handler_type(int,int,struct sigcontext*,char *));
23: EXTERN_C_END
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)
36: #undef __FUNCT__
38: sigfpe_handler_type PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp,char *addr)
39: {
40: int err_ind = -1,j,ierr;
43: for (j = 0 ; error_codes[j].code_no ; j++) {
44: if (error_codes[j].code_no == code) err_ind = j;
45: }
47: if (err_ind >= 0) {
48: (*PetscErrorPrintf)("*** %s occurred at pc=%X ***n",error_codes[err_ind].name,SIGPC(scp));
49: } else {
50: (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***n",code,SIGPC(scp));
51: }
52: PetscError(PETSC_ERR_FP,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
53: MPI_Abort(PETSC_COMM_WORLD,0);
54: return(0);
55: }
57: #undef __FUNCT__
59: /*@C
60: PetscSetFPTrap - Enables traps/exceptions on common floating point errors.
61: This option may not work on certain machines.
63: Not Collective
65: Input Parameters:
66: . flag - PETSC_FP_TRAP_ON, PETSC_FP_TRAP_OFF.
68: Options Database Keys:
69: . -fp_trap - Activates floating point trapping
71: Level: advanced
73: Description:
74: On systems that support it, this routine causes floating point
75: overflow, divide-by-zero, and invalid-operand (e.g., a NaN) to
76: cause a message to be printed and the program to exit.
78: Caution:
79: On certain machines, in particular the IBM rs6000, floating point
80: trapping is VERY slow!
82: Concepts: floating point exceptions^trapping
83: Concepts: divide by zero
85: @*/
86: int PetscSetFPTrap(PetscFPTrap flag)
87: {
88: char *out;
91: /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */
92: (void) ieee_flags("clear","exception","all",&out);
93: if (flag == PETSC_FP_TRAP_ON) {
94: if (ieee_handler("set","common",PetscDefaultFPTrap)) {
95: /*
96: To trap more fp exceptions, including undrflow, change the above line to
97: if (ieee_handler("set","all",PetscDefaultFPTrap)) {
98: */
99: (*PetscErrorPrintf)("Can't set floatingpoint handlern");
100: }
101: } else {
102: if (ieee_handler("clear","common",PetscDefaultFPTrap)) {
103: (*PetscErrorPrintf)("Can't clear floatingpoint handlern");
104: }
105: }
106: return(0);
107: }
109: /* -------------------------------------------------------------------------------------------*/
110: #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP)
111: #include <sunmath.h>
112: #include <floatingpoint.h>
113: #include <siginfo.h>
114: #include <ucontext.h>
116: struct { int code_no; char *name; } error_codes[] = {
117: { FPE_FLTINV,"invalid floating point operand"},
118: { FPE_FLTRES,"inexact floating point result"},
119: { FPE_FLTDIV,"division-by-zero"},
120: { FPE_FLTUND,"floating point underflow"},
121: { FPE_FLTOVF,"floating point overflow"},
122: { 0, "unknown error"}
123: };
124: #define SIGPC(scp) (scp->si_addr)
126: #undef __FUNCT__
128: void PetscDefaultFPTrap(int sig,siginfo_t *scp,ucontext_t *uap)
129: {
130: int err_ind,j,ierr,code = scp->si_code;
133: err_ind = -1 ;
134: for (j = 0 ; error_codes[j].code_no ; j++) {
135: if (error_codes[j].code_no == code) err_ind = j;
136: }
138: if (err_ind >= 0) {
139: (*PetscErrorPrintf)("*** %s occurred at pc=%X ***n",error_codes[err_ind].name,SIGPC(scp));
140: } else {
141: (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***n",code,SIGPC(scp));
142: }
143: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
144: MPI_Abort(PETSC_COMM_WORLD,0);
145: }
147: #undef __FUNCT__
149: int PetscSetFPTrap(PetscFPTrap flag)
150: {
151: char *out;
154: /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */
155: (void) ieee_flags("clear","exception","all",&out);
156: if (flag == PETSC_FP_TRAP_ON) {
157: if (ieee_handler("set","common",(sigfpe_handler_type)PetscDefaultFPTrap)) {
158: (*PetscErrorPrintf)("Can't set floating point handlern");
159: }
160: } else {
161: if (ieee_handler("clear","common",(sigfpe_handler_type)PetscDefaultFPTrap)) {
162: (*PetscErrorPrintf)("Can't clear floatingpoint handlern");
163: }
164: }
165: return(0);
166: }
168: /* ------------------------------------------------------------------------------------------*/
170: #elif defined (PETSC_HAVE_IRIX_STYLE_FPTRAP)
171: #include <sigfpe.h>
172: struct { int code_no; char *name; } error_codes[] = {
173: { _INVALID ,"IEEE operand error" },
174: { _OVERFL ,"floating point overflow" },
175: { _UNDERFL ,"floating point underflow" },
176: { _DIVZERO ,"floating point divide" },
177: { 0 ,"unknown error" }
178: } ;
179: #undef __FUNCT__
181: void PetscDefaultFPTrap(unsigned exception[],int val[])
182: {
183: int err_ind,j,code;
186: code = exception[0];
187: err_ind = -1 ;
188: for (j = 0 ; error_codes[j].code_no ; j++){
189: if (error_codes[j].code_no == code) err_ind = j;
190: }
191: if (err_ind >= 0){
192: (*PetscErrorPrintf)("*** %s occurred ***n",error_codes[err_ind].name);
193: } else{
194: (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***n",code);
195: }
196: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
197: MPI_Abort(PETSC_COMM_WORLD,0);
198: }
200: #undef __FUNCT__
202: int PetscSetFPTrap(PetscFPTrap flag)
203: {
205: if (flag == PETSC_FP_TRAP_ON) {
206: handle_sigfpes(_ON,_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,PetscDefaultFPTrap,_ABORT_ON_ERROR,0);
207: } else {
208: handle_sigfpes(_OFF,_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,0,_ABORT_ON_ERROR,0);
209: }
210: return(0);
211: }
212: /*----------------------------------------------- --------------------------------------------*/
213: /* In "fast" mode, floating point traps are imprecise and ignored.
214: This is the reason for the fptrap(FP_TRAP_SYNC) call */
215: #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP)
216: struct sigcontext;
217: #include <fpxcp.h>
218: #include <fptrap.h>
219: #include <stdlib.h>
220: #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000)
221: #define FPE_FLTOVF_TRAP (fptrap_t)(0x10000000)
222: #define FPE_FLTUND_TRAP (fptrap_t)(0x08000000)
223: #define FPE_FLTDIV_TRAP (fptrap_t)(0x04000000)
224: #define FPE_FLTINEX_TRAP (fptrap_t)(0x02000000)
226: struct { int code_no; char *name; } error_codes[] = {
227: {FPE_FLTOPERR_TRAP ,"IEEE operand error" },
228: { FPE_FLTOVF_TRAP ,"floating point overflow" },
229: { FPE_FLTUND_TRAP ,"floating point underflow" },
230: { FPE_FLTDIV_TRAP ,"floating point divide" },
231: { FPE_FLTINEX_TRAP ,"inexact floating point result" },
232: { 0 ,"unknown error" }
233: } ;
234: #define SIGPC(scp) (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */
235: /*
236: For some reason, scp->sc_jmpbuf does not work on the RS6000, even though
237: it looks like it should from the include definitions. It is probably
238: some strange interaction with the "POSIX_SOURCE" that we require.
239: */
241: #undef __FUNCT__
243: void PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp)
244: {
245: int ierr,err_ind,j;
246: fp_ctx_t flt_context;
249: fp_sh_trap_info(scp,&flt_context);
250:
251: err_ind = -1 ;
252: for (j = 0 ; error_codes[j].code_no ; j++) {
253: if (error_codes[j].code_no == flt_context.trap) err_ind = j;
254: }
256: if (err_ind >= 0){
257: (*PetscErrorPrintf)("*** %s occurred ***n",error_codes[err_ind].name);
258: } else{
259: (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***n",flt_context.trap);
260: }
261: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
262: MPI_Abort(PETSC_COMM_WORLD,0);
263: }
265: #undef __FUNCT__
267: int PetscSetFPTrap(PetscFPTrap on)
268: {
269: int flag;
272: if (on == PETSC_FP_TRAP_ON) {
273: signal(SIGFPE,(void (*)(int))PetscDefaultFPTrap);
274: fp_trap(FP_TRAP_SYNC);
275: fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
276: /* fp_enable(mask) for individual traps. Values are:
277: TRP_INVALID
278: TRP_DIV_BY_ZERO
279: TRP_OVERFLOW
280: TRP_UNDERFLOW
281: TRP_INEXACT
282: Can OR then together.
283: fp_enable_all(); for all traps.
284: */
285: } else {
286: signal(SIGFPE,SIG_DFL);
287: fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
288: fp_trap(FP_TRAP_OFF);
289: }
290: return(0);
291: }
293: /* -------------------------Default -----------------------------------*/
294: #else
295: struct { int code_no; char *name; } error_codes[] = {
296: { 0 ,"unknown error" }
297: } ;
298: #undef __FUNCT__
300: void PetscDefaultFPTrap(int sig)
301: {
303: (*PetscErrorPrintf)("*** floating point error occurred ***n");
304: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
305: MPI_Abort(PETSC_COMM_WORLD,0);
306: }
307: #undef __FUNCT__
309: int PetscSetFPTrap(PetscFPTrap on)
310: {
312: if (on == PETSC_FP_TRAP_ON) {
313: if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) {
314: (*PetscErrorPrintf)("Can't set floatingpoint handlern");
315: }
316: } else {
317: if (SIG_ERR == signal(SIGFPE,SIG_DFL)) {
318: (*PetscErrorPrintf)("Can't clear floatingpoint handlern");
319: }
320: }
321: return(0);
322: }
323: #endif