Actual source code: fp.c

  1: /*
  2: *        IEEE error handler for all machines. Since each machine has 
  3: *   enough slight differences we have completely separate codes for each one.
  4: *
  5: */
 6:  #include petsc.h
 7:  #include petscsys.h
  8: #include <signal.h>
  9: #if defined(PETSC_HAVE_STDLIB_H)
 10: #include <stdlib.h>
 11: #endif
 12: #include "petscfix.h"


 15: /*--------------------------------------- ---------------------------------------------------*/
 16: #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP)
 17: #include <floatingpoint.h>

 20: PetscErrorCode ieee_flags(char*,char*,char*,char**);
 21: PetscErrorCode ieee_handler(char *,char *,sigfpe_handler_type(int,int,struct sigcontext*,char *));

 24: struct { int code_no; char *name; } error_codes[] = {
 25:            { FPE_INTDIV_TRAP        ,"integer divide" },
 26:            { FPE_FLTOPERR_TRAP        ,"IEEE operand error" },
 27:            { FPE_FLTOVF_TRAP        ,"floating point overflow" },
 28:            { FPE_FLTUND_TRAP        ,"floating point underflow" },
 29:            { FPE_FLTDIV_TRAP        ,"floating pointing divide" },
 30:            { FPE_FLTINEX_TRAP        ,"inexact floating point result" },
 31:            { 0                        ,"unknown error" }
 32: } ;
 33: #define SIGPC(scp) (scp->sc_pc)

 37: sigfpe_handler_type PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp,char *addr)
 38: {
 40:   int err_ind = -1,j;

 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: }

 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: PetscErrorCode 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 handler\n");
100:     }
101:   } else {
102:     if (ieee_handler("clear","common",PetscDefaultFPTrap)) {
103:       (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
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)

128: void PetscDefaultFPTrap(int sig,siginfo_t *scp,ucontext_t *uap)
129: {
130:   int err_ind,j,code = scp->si_code;

134:   err_ind = -1 ;
135:   for (j = 0 ; error_codes[j].code_no ; j++) {
136:     if (error_codes[j].code_no == code) err_ind = j;
137:   }

139:   if (err_ind >= 0) {
140:     (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp));
141:   } else {
142:     (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp));
143:   }
144:   PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
145:   MPI_Abort(PETSC_COMM_WORLD,0);
146: }

150: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
151: {
152:   char *out;

155:   /* Clear accumulated exceptions.  Used to suppress meaningless messages from f77 programs */
156:   (void) ieee_flags("clear","exception","all",&out);
157:   if (flag == PETSC_FP_TRAP_ON) {
158:     if (ieee_handler("set","common",(sigfpe_handler_type)PetscDefaultFPTrap)) {
159:       (*PetscErrorPrintf)("Can't set floating point handler\n");
160:     }
161:   } else {
162:     if (ieee_handler("clear","common",(sigfpe_handler_type)PetscDefaultFPTrap)) {
163:      (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
164:     }
165:   }
166:   return(0);
167: }

169: /* ------------------------------------------------------------------------------------------*/

171: #elif defined (PETSC_HAVE_IRIX_STYLE_FPTRAP)
172: #include <sigfpe.h>
173: struct { int code_no; char *name; } error_codes[] = {
174:        { _INVALID   ,"IEEE operand error" },
175:        { _OVERFL    ,"floating point overflow" },
176:        { _UNDERFL   ,"floating point underflow" },
177:        { _DIVZERO   ,"floating point divide" },
178:        { 0          ,"unknown error" }
179: } ;
182: void PetscDefaultFPTrap(unsigned exception[],int val[])
183: {
184:   int err_ind,j,code;

187:   code = exception[0];
188:   err_ind = -1 ;
189:   for (j = 0 ; error_codes[j].code_no ; j++){
190:     if (error_codes[j].code_no == code) err_ind = j;
191:   }
192:   if (err_ind >= 0){
193:     (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name);
194:   } else{
195:     (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",code);
196:   }
197:   PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
198:   MPI_Abort(PETSC_COMM_WORLD,0);
199: }

203: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
204: {
206:   if (flag == PETSC_FP_TRAP_ON) {
207:     handle_sigfpes(_ON,_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,PetscDefaultFPTrap,_ABORT_ON_ERROR,0);
208:   } else {
209:     handle_sigfpes(_OFF,_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,0,_ABORT_ON_ERROR,0);
210:   }
211:   return(0);
212: }
213: /*----------------------------------------------- --------------------------------------------*/
214: /* In "fast" mode, floating point traps are imprecise and ignored.
215:    This is the reason for the fptrap(FP_TRAP_SYNC) call */
216: #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP) 
217: struct sigcontext;
218: #include <fpxcp.h>
219: #include <fptrap.h>
220: #include <stdlib.h>
221: #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000)
222: #define FPE_FLTOVF_TRAP   (fptrap_t)(0x10000000)
223: #define FPE_FLTUND_TRAP   (fptrap_t)(0x08000000)
224: #define FPE_FLTDIV_TRAP   (fptrap_t)(0x04000000)
225: #define FPE_FLTINEX_TRAP  (fptrap_t)(0x02000000)

227: struct { int code_no; char *name; } error_codes[] = {
228:            {FPE_FLTOPERR_TRAP        ,"IEEE operand error" },
229:            { FPE_FLTOVF_TRAP        ,"floating point overflow" },
230:            { FPE_FLTUND_TRAP        ,"floating point underflow" },
231:            { FPE_FLTDIV_TRAP        ,"floating point divide" },
232:            { FPE_FLTINEX_TRAP        ,"inexact floating point result" },
233:            { 0                        ,"unknown error" }
234: } ;
235: #define SIGPC(scp) (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */
236: /* 
237:    For some reason, scp->sc_jmpbuf does not work on the RS6000, even though
238:    it looks like it should from the include definitions.  It is probably
239:    some strange interaction with the "POSIX_SOURCE" that we require.
240: */

244: void PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp)
245: {
247:   int      err_ind,j;
248:   fp_ctx_t flt_context;

251:   fp_sh_trap_info(scp,&flt_context);
252: 
253:   err_ind = -1 ;
254:   for (j = 0 ; error_codes[j].code_no ; j++) {
255:     if (error_codes[j].code_no == flt_context.trap) err_ind = j;
256:   }

258:   if (err_ind >= 0){
259:     (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name);
260:   } else{
261:     (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",flt_context.trap);
262:   }
263:   PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
264:   MPI_Abort(PETSC_COMM_WORLD,0);
265: }

269: PetscErrorCode PetscSetFPTrap(PetscFPTrap on)
270: {
271:   int flag;

274:   if (on == PETSC_FP_TRAP_ON) {
275:     signal(SIGFPE,(void (*)(int))PetscDefaultFPTrap);
276:     fp_trap(FP_TRAP_SYNC);
277:     fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
278:     /* fp_enable(mask) for individual traps.  Values are:
279:        TRP_INVALID
280:        TRP_DIV_BY_ZERO
281:        TRP_OVERFLOW
282:        TRP_UNDERFLOW
283:        TRP_INEXACT
284:        Can OR then together.
285:        fp_enable_all(); for all traps.
286:     */
287:   } else {
288:     signal(SIGFPE,SIG_DFL);
289:     fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
290:     fp_trap(FP_TRAP_OFF);
291:   }
292:   return(0);
293: }

295: /* -------------------------Default -----------------------------------*/
296: #else 
297: struct { int code_no; const char *name; } error_codes[] = {
298:            { 0                ,"unknown error" }
299: } ;
303: void PetscDefaultFPTrap(int sig)
304: {
306:   (*PetscErrorPrintf)("*** floating point error occurred ***\n");
307:   PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_FP,1,"floating point error");
308:   MPI_Abort(PETSC_COMM_WORLD,0);
309: }
313: PetscErrorCode PetscSetFPTrap(PetscFPTrap on)
314: {
316:   if (on == PETSC_FP_TRAP_ON) {
317:     if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) {
318:       (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
319:     }
320:   } else {
321:     if (SIG_ERR == signal(SIGFPE,SIG_DFL)) {
322:       (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
323:     }
324:   }
325:   return(0);
326: }
327: #endif