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