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