Actual source code: fp.c
2: /*
3: IEEE error handler for all machines. Since each OS has
4: enough slight differences we have completely separate codes for each one.
5: */
7: /*
8: This feature test macro provides FE_NOMASK_ENV on GNU. It must be defined
9: at the top of the file because other headers may pull in fenv.h even when
10: not strictly necessary. Strictly speaking, we could include ONLY petscconf.h,
11: check PETSC_HAVE_FENV_H, and only define _GNU_SOURCE in that case, but such
12: shenanigans ought to be unnecessary.
13: */
14: #if !defined(_GNU_SOURCE)
15: #define _GNU_SOURCE
16: #endif
18: #include <petsc/private/petscimpl.h>
19: #include <signal.h>
21: struct PetscFPTrapLink {
22: PetscFPTrap trapmode;
23: struct PetscFPTrapLink *next;
24: };
25: static PetscFPTrap _trapmode = PETSC_FP_TRAP_OFF; /* Current trapping mode; see PetscDetermineInitialFPTrap() */
26: static struct PetscFPTrapLink *_trapstack; /* Any pushed states of _trapmode */
28: /*@
29: PetscFPTrapPush - push a floating point trapping mode, restored using PetscFPTrapPop()
31: Not Collective
33: Input Parameter:
34: . trap - PETSC_FP_TRAP_ON or PETSC_FP_TRAP_OFF
36: Level: advanced
38: Notes:
39: This only changes the trapping if the new mode is different than the current mode.
41: This routine is called to turn off trapping for certain LAPACK routines that assume that dividing
42: by zero is acceptable. In particular the routine ieeeck().
44: Most systems by default have all trapping turned off, but certain Fortran compilers have
45: link flags that turn on trapping before the program begins.
46: $ gfortran -ffpe-trap=invalid,zero,overflow,underflow,denormal
47: $ ifort -fpe0
49: .seealso: PetscFPTrapPop(), PetscSetFPTrap(), PetscDetermineInitialFPTrap()
50: @*/
51: PetscErrorCode PetscFPTrapPush(PetscFPTrap trap)
52: {
53: struct PetscFPTrapLink *link;
55: PetscNew(&link);
56: link->trapmode = _trapmode;
57: link->next = _trapstack;
58: _trapstack = link;
59: if (trap != _trapmode) PetscSetFPTrap(trap);
60: return 0;
61: }
63: /*@
64: PetscFPTrapPop - push a floating point trapping mode, to be restored using PetscFPTrapPop()
66: Not Collective
68: Level: advanced
70: .seealso: PetscFPTrapPush(), PetscSetFPTrap(), PetscDetermineInitialFPTrap()
71: @*/
72: PetscErrorCode PetscFPTrapPop(void)
73: {
74: struct PetscFPTrapLink *link;
76: if (_trapstack->trapmode != _trapmode) PetscSetFPTrap(_trapstack->trapmode);
77: link = _trapstack;
78: _trapstack = _trapstack->next;
79: PetscFree(link);
80: return 0;
81: }
83: /*--------------------------------------- ---------------------------------------------------*/
84: #if defined(PETSC_HAVE_SUN4_STYLE_FPTRAP)
85: #include <floatingpoint.h>
87: PETSC_EXTERN PetscErrorCode ieee_flags(char*,char*,char*,char**);
88: PETSC_EXTERN PetscErrorCode ieee_handler(char*,char*,sigfpe_handler_type(int,int,struct sigcontext*,char*));
90: static struct { int code_no; char *name; } error_codes[] = {
91: { FPE_INTDIV_TRAP ,"integer divide" },
92: { FPE_FLTOPERR_TRAP ,"IEEE operand error" },
93: { FPE_FLTOVF_TRAP ,"floating point overflow" },
94: { FPE_FLTUND_TRAP ,"floating point underflow" },
95: { FPE_FLTDIV_TRAP ,"floating pointing divide" },
96: { FPE_FLTINEX_TRAP ,"inexact floating point result" },
97: { 0 ,"unknown error" }
98: };
99: #define SIGPC(scp) (scp->sc_pc)
101: sigfpe_handler_type PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp,char *addr)
102: {
103: int err_ind = -1;
105: for (int j = 0; error_codes[j].code_no; j++) {
106: if (error_codes[j].code_no == code) err_ind = j;
107: }
109: if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp));
110: else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp));
112: (void)PetscError(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error");
113: PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP);
114: return 0;
115: }
117: /*@
118: PetscSetFPTrap - Enables traps/exceptions on common floating point errors.
119: This option may not work on certain systems.
121: Not Collective
123: Input Parameters:
124: . flag - PETSC_FP_TRAP_ON, PETSC_FP_TRAP_OFF.
126: Options Database Keys:
127: . -fp_trap - Activates floating point trapping
129: Level: advanced
131: Description:
132: On systems that support it, when called with PETSC_FP_TRAP_ON this routine causes floating point
133: underflow, overflow, divide-by-zero, and invalid-operand (e.g., a NaN) to
134: cause a message to be printed and the program to exit.
136: Note:
137: On many common systems, the floating
138: point exception state is not preserved from the location where the trap
139: occurred through to the signal handler. In this case, the signal handler
140: will just say that an unknown floating point exception occurred and which
141: function it occurred in. If you run with -fp_trap in a debugger, it will
142: break on the line where the error occurred. On systems that support C99
143: floating point exception handling You can check which
144: exception occurred using fetestexcept(FE_ALL_EXCEPT). See fenv.h
145: (usually at /usr/include/bits/fenv.h) for the enum values on your system.
147: Caution:
148: On certain machines, in particular the IBM PowerPC, floating point
149: trapping may be VERY slow!
151: .seealso: PetscFPTrapPush(), PetscFPTrapPop(), PetscDetermineInitialFPTrap()
152: @*/
153: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
154: {
155: char *out;
157: /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */
158: (void) ieee_flags("clear","exception","all",&out);
159: if (flag == PETSC_FP_TRAP_ON) {
160: /*
161: To trap more fp exceptions, including underflow, change the line below to
162: if (ieee_handler("set","all",PetscDefaultFPTrap)) {
163: */
164: if (ieee_handler("set","common",PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
165: } else if (ieee_handler("clear","common",PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
167: _trapmode = flag;
168: return 0;
169: }
171: /*@
172: PetscDetermineInitialFPTrap - Attempts to determine the floating point trapping that exists when PetscInitialize() is called
174: Not Collective
176: Notes:
177: Currently only supported on Linux and MacOS. Checks if divide by zero is enable and if so declares that trapping is on.
179: Level: advanced
181: .seealso: PetscFPTrapPush(), PetscFPTrapPop(), PetscDetermineInitialFPTrap()
182: @*/
183: PetscErrorCode PetscDetermineInitialFPTrap(void)
184: {
185: PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");
186: return 0;
187: }
189: /* -------------------------------------------------------------------------------------------*/
190: #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP)
191: #include <sunmath.h>
192: #include <floatingpoint.h>
193: #include <siginfo.h>
194: #include <ucontext.h>
196: static struct { int code_no; char *name; } error_codes[] = {
197: { FPE_FLTINV,"invalid floating point operand"},
198: { FPE_FLTRES,"inexact floating point result"},
199: { FPE_FLTDIV,"division-by-zero"},
200: { FPE_FLTUND,"floating point underflow"},
201: { FPE_FLTOVF,"floating point overflow"},
202: { 0, "unknown error"}
203: };
204: #define SIGPC(scp) (scp->si_addr)
206: void PetscDefaultFPTrap(int sig,siginfo_t *scp,ucontext_t *uap)
207: {
208: int err_ind = -1,code = scp->si_code;
210: for (int j = 0; error_codes[j].code_no; j++) {
211: if (error_codes[j].code_no == code) err_ind = j;
212: }
214: if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp));
215: else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp));
217: (void)PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error");
218: PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP);
219: }
221: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
222: {
223: char *out;
225: /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */
226: (void) ieee_flags("clear","exception","all",&out);
227: if (flag == PETSC_FP_TRAP_ON) {
228: if (ieee_handler("set","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n");
229: } else {
230: if (ieee_handler("clear","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
231: }
232: _trapmode = flag;
233: return 0;
234: }
236: PetscErrorCode PetscDetermineInitialFPTrap(void)
237: {
238: PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");
239: return 0;
240: }
242: /* ------------------------------------------------------------------------------------------*/
243: #elif defined(PETSC_HAVE_IRIX_STYLE_FPTRAP)
244: #include <sigfpe.h>
245: static struct { int code_no; char *name; } error_codes[] = {
246: { _INVALID ,"IEEE operand error" },
247: { _OVERFL ,"floating point overflow" },
248: { _UNDERFL ,"floating point underflow" },
249: { _DIVZERO ,"floating point divide" },
250: { 0 ,"unknown error" }
251: } ;
252: void PetscDefaultFPTrap(unsigned exception[],int val[])
253: {
254: int err_ind = -1,code = exception[0];
256: for (int j = 0; error_codes[j].code_no; j++) {
257: if (error_codes[j].code_no == code) err_ind = j;
258: }
259: if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name);
260: else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",code);
262: (void)PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error");
263: PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP);
264: }
266: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
267: {
268: if (flag == PETSC_FP_TRAP_ON) handle_sigfpes(_ON,,_EN_UNDERFL|_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,PetscDefaultFPTrap,_ABORT_ON_ERROR,0);
269: else handle_sigfpes(_OFF,_EN_UNDERFL|_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,0,_ABORT_ON_ERROR,0);
270: _trapmode = flag;
271: return 0;
272: }
274: PetscErrorCode PetscDetermineInitialFPTrap(void)
275: {
276: PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");
277: return 0;
278: }
280: /* -------------------------------------------------------------------------------------------*/
281: #elif defined(PETSC_HAVE_SOLARIS_STYLE_FPTRAP)
282: #include <sunmath.h>
283: #include <floatingpoint.h>
284: #include <siginfo.h>
285: #include <ucontext.h>
287: static struct { int code_no; char *name; } error_codes[] = {
288: { FPE_FLTINV,"invalid floating point operand"},
289: { FPE_FLTRES,"inexact floating point result"},
290: { FPE_FLTDIV,"division-by-zero"},
291: { FPE_FLTUND,"floating point underflow"},
292: { FPE_FLTOVF,"floating point overflow"},
293: { 0, "unknown error"}
294: };
295: #define SIGPC(scp) (scp->si_addr)
297: void PetscDefaultFPTrap(int sig,siginfo_t *scp,ucontext_t *uap)
298: {
299: int err_ind = -1,code = scp->si_code;
301: err_ind = -1;
302: for (int j = 0; error_codes[j].code_no; j++) {
303: if (error_codes[j].code_no == code) err_ind = j;
304: }
306: if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred at pc=%X ***\n",error_codes[err_ind].name,SIGPC(scp));
307: else (*PetscErrorPrintf)("*** floating point error 0x%x occurred at pc=%X ***\n",code,SIGPC(scp));
309: (void)PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error");
310: PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP);
311: }
313: PetscErrorCode PetscSetFPTrap(PetscFPTrap flag)
314: {
315: char *out;
317: /* Clear accumulated exceptions. Used to suppress meaningless messages from f77 programs */
318: (void) ieee_flags("clear","exception","all",&out);
319: if (flag == PETSC_FP_TRAP_ON) {
320: if (ieee_handler("set","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floating point handler\n");
321: } else {
322: if (ieee_handler("clear","common",(sigfpe_handler_type)PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
323: }
324: _trapmode = flag;
325: return 0;
326: }
328: PetscErrorCode PetscDetermineInitialFPTrap(void)
329: {
330: PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");
331: return 0;
332: }
334: /*----------------------------------------------- --------------------------------------------*/
335: #elif defined(PETSC_HAVE_RS6000_STYLE_FPTRAP)
336: /* In "fast" mode, floating point traps are imprecise and ignored.
337: This is the reason for the fptrap(FP_TRAP_SYNC) call */
338: struct sigcontext;
339: #include <fpxcp.h>
340: #include <fptrap.h>
341: #define FPE_FLTOPERR_TRAP (fptrap_t)(0x20000000)
342: #define FPE_FLTOVF_TRAP (fptrap_t)(0x10000000)
343: #define FPE_FLTUND_TRAP (fptrap_t)(0x08000000)
344: #define FPE_FLTDIV_TRAP (fptrap_t)(0x04000000)
345: #define FPE_FLTINEX_TRAP (fptrap_t)(0x02000000)
347: static struct { int code_no; char *name; } error_codes[] = {
348: {FPE_FLTOPERR_TRAP ,"IEEE operand error" },
349: { FPE_FLTOVF_TRAP ,"floating point overflow" },
350: { FPE_FLTUND_TRAP ,"floating point underflow" },
351: { FPE_FLTDIV_TRAP ,"floating point divide" },
352: { FPE_FLTINEX_TRAP ,"inexact floating point result" },
353: { 0 ,"unknown error" }
354: } ;
355: #define SIGPC(scp) (0) /* Info MIGHT be in scp->sc_jmpbuf.jmp_context.iar */
356: /*
357: For some reason, scp->sc_jmpbuf does not work on the RS6000, even though
358: it looks like it should from the include definitions. It is probably
359: some strange interaction with the "POSIX_SOURCE" that we require.
360: */
362: void PetscDefaultFPTrap(int sig,int code,struct sigcontext *scp)
363: {
365: int err_ind,j;
366: fp_ctx_t flt_context;
368: fp_sh_trap_info(scp,&flt_context);
370: err_ind = -1;
371: for (j = 0; error_codes[j].code_no; j++) {
372: if (error_codes[j].code_no == flt_context.trap) err_ind = j;
373: }
375: if (err_ind >= 0) (*PetscErrorPrintf)("*** %s occurred ***\n",error_codes[err_ind].name);
376: else (*PetscErrorPrintf)("*** floating point error 0x%x occurred ***\n",flt_context.trap);
378: PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error");
379: PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP);
380: }
382: PetscErrorCode PetscSetFPTrap(PetscFPTrap on)
383: {
384: if (on == PETSC_FP_TRAP_ON) {
385: signal(SIGFPE,(void (*)(int))PetscDefaultFPTrap);
386: fp_trap(FP_TRAP_SYNC);
387: fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW);
388: /* fp_enable(mask) for individual traps. Values are:
389: TRP_INVALID
390: TRP_DIV_BY_ZERO
391: TRP_OVERFLOW
392: TRP_UNDERFLOW
393: TRP_INEXACT
394: Can OR then together.
395: fp_enable_all(); for all traps.
396: */
397: } else {
398: signal(SIGFPE,SIG_DFL);
399: fp_disable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW | TRP_UNDERFLOW);
400: fp_trap(FP_TRAP_OFF);
401: }
402: _trapmode = on;
403: return 0;
404: }
406: PetscErrorCode PetscDetermineInitialFPTrap(void)
407: {
408: PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");
409: return 0;
410: }
412: /* ------------------------------------------------------------*/
413: #elif defined(PETSC_HAVE_WINDOWS_COMPILERS)
414: #include <float.h>
415: void PetscDefaultFPTrap(int sig)
416: {
417: (*PetscErrorPrintf)("*** floating point error occurred ***\n");
418: PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error");
419: PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP);
420: }
422: PetscErrorCode PetscSetFPTrap(PetscFPTrap on)
423: {
424: unsigned int cw;
426: if (on == PETSC_FP_TRAP_ON) {
427: cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW;
429: } else {
430: cw = 0;
432: }
433: (void)_controlfp(0, cw);
434: _trapmode = on;
435: return 0;
436: }
438: PetscErrorCode PetscDetermineInitialFPTrap(void)
439: {
440: PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");
441: return 0;
442: }
444: /* ------------------------------------------------------------*/
445: #elif defined(PETSC_HAVE_FENV_H) && !defined(__cplusplus)
446: /*
447: C99 style floating point environment.
449: Note that C99 merely specifies how to save, restore, and clear the floating
450: point environment as well as defining an enumeration of exception codes. In
451: particular, C99 does not specify how to make floating point exceptions raise
452: a signal. Glibc offers this capability through FE_NOMASK_ENV (or with finer
453: granularity, feenableexcept()), xmmintrin.h offers _MM_SET_EXCEPTION_MASK().
454: */
455: #include <fenv.h>
456: typedef struct {int code; const char *name;} FPNode;
457: static const FPNode error_codes[] = {
458: {FE_DIVBYZERO,"divide by zero"},
459: {FE_INEXACT, "inexact floating point result"},
460: {FE_INVALID, "invalid floating point arguments (domain error)"},
461: {FE_OVERFLOW, "floating point overflow"},
462: {FE_UNDERFLOW,"floating point underflow"},
463: {0 ,"unknown error"}
464: };
466: void PetscDefaultFPTrap(int sig)
467: {
468: const FPNode *node;
469: int code;
470: PetscBool matched = PETSC_FALSE;
472: /* Note: While it is possible for the exception state to be preserved by the
473: * kernel, this seems to be rare which makes the following flag testing almost
474: * useless. But on a system where the flags can be preserved, it would provide
475: * more detail.
476: */
477: code = fetestexcept(FE_ALL_EXCEPT);
478: for (node=&error_codes[0]; node->code; node++) {
479: if (code & node->code) {
480: matched = PETSC_TRUE;
481: (*PetscErrorPrintf)("*** floating point error \"%s\" occurred ***\n",node->name);
482: code &= ~node->code; /* Unset this flag since it has been processed */
483: }
484: }
485: if (!matched || code) { /* If any remaining flags are set, or we didn't process any flags */
486: (*PetscErrorPrintf)("*** unknown floating point error occurred ***\n");
487: (*PetscErrorPrintf)("The specific exception can be determined by running in a debugger. When the\n");
488: (*PetscErrorPrintf)("debugger traps the signal, the exception can be found with fetestexcept(0x%x)\n",FE_ALL_EXCEPT);
489: (*PetscErrorPrintf)("where the result is a bitwise OR of the following flags:\n");
490: (*PetscErrorPrintf)("FE_INVALID=0x%x FE_DIVBYZERO=0x%x FE_OVERFLOW=0x%x FE_UNDERFLOW=0x%x FE_INEXACT=0x%x\n",FE_INVALID,FE_DIVBYZERO,FE_OVERFLOW,FE_UNDERFLOW,FE_INEXACT);
491: }
493: (*PetscErrorPrintf)("Try option -start_in_debugger\n");
494: #if PetscDefined(USE_DEBUG)
495: (*PetscErrorPrintf)("likely location of problem given in stack below\n");
496: (*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n");
497: PetscStackView(PETSC_STDOUT);
498: #else
499: (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
500: (*PetscErrorPrintf)("with -start_in_debugger to get more information on the crash.\n");
501: #endif
502: PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_INITIAL,"trapped floating point error");
503: PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP);
504: }
506: PetscErrorCode PetscSetFPTrap(PetscFPTrap on)
507: {
508: if (on == PETSC_FP_TRAP_ON) {
509: /* Clear any flags that are currently set so that activating trapping will not immediately call the signal handler. */
511: #if defined(FE_NOMASK_ENV)
512: /* Could use fesetenv(FE_NOMASK_ENV), but that causes spurious exceptions (like gettimeofday() -> PetscLogDouble). */
514: #elif defined PETSC_HAVE_XMMINTRIN_H
515: _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_DIV_ZERO);
516: _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_UNDERFLOW);
517: _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_OVERFLOW);
518: _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~_MM_MASK_INVALID);
519: #else
520: /* C99 does not provide a way to modify the environment so there is no portable way to activate trapping. */
521: #endif
523: } else {
525: /* can use _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | _MM_MASK_UNDERFLOW); if PETSC_HAVE_XMMINTRIN_H exists */
527: }
528: _trapmode = on;
529: return 0;
530: }
532: PetscErrorCode PetscDetermineInitialFPTrap(void)
533: {
534: #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
535: unsigned int flags;
536: #endif
538: #if defined(FE_NOMASK_ENV)
539: flags = fegetexcept();
540: if (flags & FE_DIVBYZERO) {
541: #elif defined PETSC_HAVE_XMMINTRIN_H
542: flags = _MM_GET_EXCEPTION_MASK();
543: if (!(flags & _MM_MASK_DIV_ZERO)) {
544: #else
545: PetscInfo(NULL,"Floating point trapping unknown, assuming off\n");
546: return 0;
547: #endif
548: #if defined(FE_NOMASK_ENV) || defined PETSC_HAVE_XMMINTRIN_H
549: _trapmode = PETSC_FP_TRAP_ON;
550: PetscInfo(NULL,"Floating point trapping is on by default %d\n",flags);
551: } else {
552: _trapmode = PETSC_FP_TRAP_OFF;
553: PetscInfo(NULL,"Floating point trapping is off by default %d\n",flags);
554: }
555: return 0;
556: #endif
557: }
559: /* ------------------------------------------------------------*/
560: #elif defined(PETSC_HAVE_IEEEFP_H)
561: #include <ieeefp.h>
562: void PetscDefaultFPTrap(int sig)
563: {
564: (*PetscErrorPrintf)("*** floating point error occurred ***\n");
565: PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error");
566: PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP);
567: }
569: PetscErrorCode PetscSetFPTrap(PetscFPTrap on)
570: {
571: if (on == PETSC_FP_TRAP_ON) {
572: #if defined(PETSC_HAVE_FPPRESETSTICKY)
573: fpresetsticky(fpgetsticky());
574: #elif defined(PETSC_HAVE_FPSETSTICKY)
575: fpsetsticky(fpgetsticky());
576: #endif
577: fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL | FP_X_OFL);
579: } else {
580: #if defined(PETSC_HAVE_FPPRESETSTICKY)
581: fpresetsticky(fpgetsticky());
582: #elif defined(PETSC_HAVE_FPSETSTICKY)
583: fpsetsticky(fpgetsticky());
584: #endif
585: fpsetmask(0);
587: }
588: _trapmode = on;
589: return 0;
590: }
592: PetscErrorCode PetscDetermineInitialFPTrap(void)
593: {
594: PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");
595: return 0;
596: }
598: /* -------------------------Default -----------------------------------*/
599: #else
601: void PetscDefaultFPTrap(int sig)
602: {
603: (*PetscErrorPrintf)("*** floating point error occurred ***\n");
604: PetscError(PETSC_COMM_SELF,0,"User provided function","Unknown file",PETSC_ERR_FP,PETSC_ERROR_REPEAT,"floating point error");
605: PETSCABORT(MPI_COMM_WORLD,PETSC_ERR_FP);
606: }
608: PetscErrorCode PetscSetFPTrap(PetscFPTrap on)
609: {
610: if (on == PETSC_FP_TRAP_ON) {
611: if (SIG_ERR == signal(SIGFPE,PetscDefaultFPTrap)) (*PetscErrorPrintf)("Can't set floatingpoint handler\n");
612: } else if (SIG_ERR == signal(SIGFPE,SIG_DFL)) (*PetscErrorPrintf)("Can't clear floatingpoint handler\n");
614: _trapmode = on;
615: return 0;
616: }
618: PetscErrorCode PetscDetermineInitialFPTrap(void)
619: {
620: PetscInfo(NULL,"Unable to determine initial floating point trapping. Assuming it is off\n");
621: return 0;
622: }
623: #endif