Teuchos_FloatingPointTrap.cpp

00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 
00030 #include "Teuchos_FloatingPointTrap.hpp"
00031 #include "Teuchos_TestForException.hpp"
00032 
00033 
00034 //
00035 // Implementation of floating point control
00036 //
00037 
00038 
00039 // ???
00040 
00041 
00042 //
00043 // We have floating point control!
00044 //
00045 
00046 
00047 static void ieee0(bool enableTrap);
00048 
00049 
00050 void Teuchos::doFloatingPointTrap(bool enableTrap)
00051 {
00052   ieee0(enableTrap);
00053 }
00054 
00055 
00056 
00057 //
00058 // Stuff from uninit.c from f2c and them from Sacado!
00059 //
00060 
00061 
00062 //
00063 // Up front stuff
00064 //
00065 
00066 
00067 #include <cstdio>
00068 #include <cstring>
00069 
00070 #define TYSHORT 2
00071 #define TYLONG 3
00072 #define TYREAL 4
00073 #define TYDREAL 5
00074 #define TYCOMPLEX 6
00075 #define TYDCOMPLEX 7
00076 #define TYINT1 11
00077 #define TYQUAD 14
00078 
00079 #ifndef Long
00080 #define Long long
00081 #endif // Long
00082 
00083 #ifdef __mips
00084 #define RNAN  0xffc00000
00085 #define DNAN0 0xfff80000
00086 #define DNAN1 0
00087 #endif // __mips
00088 
00089 #ifdef _PA_RISC1_1
00090 #define RNAN  0xffc00000
00091 #define DNAN0 0xfff80000
00092 #define DNAN1 0
00093 #endif // _PA_RISC1_1
00094 
00095 #ifndef RNAN
00096 #  define RNAN  0xff800001
00097 #  ifdef IEEE_MC68k
00098 #    define DNAN0 0xfff00000
00099 #    define DNAN1 1
00100 #  else
00101 #    define DNAN0 1
00102 #    define DNAN1 0xfff00000
00103 #  endif
00104 #endif /*RNAN*/
00105 
00106 
00107 static unsigned Long rnan = RNAN, dnan0 = DNAN0, dnan1 = DNAN1;
00108 
00109 double _0 = 0.;
00110 
00111 #ifndef MSpc
00112 #  ifdef MSDOS
00113 #    define MSpc
00114 #  else
00115 #    ifdef _WIN32
00116 #      define MSpc
00117 #    endif
00118 #  endif
00119 #endif
00120 
00121 
00122 //
00123 // MSpc
00124 //
00125 
00126 
00127 #ifdef MSpc
00128 
00129 #define IEEE0_done
00130 #include "cfloat"
00131 #include "csignal"
00132 
00133 static void ieee0(bool enableTrap)
00134 {
00135   TEST_FOR_EXCEPTION(
00136     enableTrap == false, std::logic_error,
00137     "Error, don't know how to turn off trap for MSpc!"
00138     );
00139 #ifndef __alpha
00140   _control87(EM_DENORMAL | EM_UNDERFLOW | EM_INEXACT, MCW_EM);
00141 #endif
00142   /* With MS VC++, compiling and linking with -Zi will permit */
00143   /* clicking to invoke the MS C++ debugger, which will show */
00144   /* the point of error -- provided SIGFPE is SIG_DFL. */
00145   signal(SIGFPE, SIG_DFL);
00146 }
00147 
00148 #endif // MSpc
00149 
00150 
00151 //
00152 // MIPS
00153 //
00154 
00155 
00156 #ifdef __mips /* must link with -lfpe */
00157 
00158 #define IEEE0_done
00159 #include <cstdlib>
00160 #include <cstdio>
00161 #include "/usr/include/sigfpe.h"  /* full pathname for lcc -N */
00162 #include "/usr/include/sys/fpu.h"
00163 
00164 static void ieeeuserhand(unsigned std::exception[5], int val[2])
00165 {
00166   fflush(stdout);
00167   fprintf(stderr,"ieee0() aborting because of ");
00168   if(std::exception[0]==_OVERFL) fprintf(stderr,"overflow\n");
00169   else if(std::exception[0]==_UNDERFL) fprintf(stderr,"underflow\n");
00170   else if(std::exception[0]==_DIVZERO) fprintf(stderr,"divide by 0\n");
00171   else if(std::exception[0]==_INVALID) fprintf(stderr,"invalid operation\n");
00172   else fprintf(stderr,"\tunknown reason\n");
00173   fflush(stderr);
00174   abort();
00175 }
00176 
00177 static void ieeeuserhand2(unsigned int **j)
00178 {
00179   fprintf(stderr,"ieee0() aborting because of confusion\n");
00180   abort();
00181 }
00182 
00183 static void ieee0(bool enableTrap)
00184 {
00185   TEST_FOR_EXCEPTION(
00186     enableTrap == false, std::logic_error,
00187     "Error, don't know how to turn off trap for MIPS!"
00188     );
00189   int i;
00190   for(i=1; i<=4; i++){
00191     sigfpe_[i].count = 1000;
00192     sigfpe_[i].trace = 1;
00193     sigfpe_[i].repls = _USER_DETERMINED;
00194     }
00195   sigfpe_[1].repls = _ZERO; /* underflow */
00196   handle_sigfpes( _ON,
00197     _EN_UNDERFL|_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,
00198     ieeeuserhand,_ABORT_ON_ERROR,ieeeuserhand2);
00199   }
00200 #endif /* mips */
00201 
00202 
00203 //
00204 // Linux
00205 //
00206 
00207 
00208 #ifdef __linux__
00209 
00210 #define IEEE0_done
00211 #include "fpu_control.h"
00212 
00213 #ifdef __alpha__
00214 #  ifndef USE_setfpucw
00215 #    define __setfpucw(x) __fpu_control = (x)
00216 #  endif
00217 #endif
00218 
00219 #ifndef _FPU_SETCW
00220 #  undef  Can_use__setfpucw
00221 #  define Can_use__setfpucw
00222 #endif
00223 
00224 static void ieee0(bool enableTrap)
00225 {
00226 
00227   TEST_FOR_EXCEPTION(
00228     enableTrap == false, std::logic_error,
00229     "Error, don't know how to turn off trap for LINUX!"
00230     );
00231 
00232 #if (defined(__mc68000__) || defined(__mc68020__) || defined(mc68020) || defined (__mc68k__))
00233 
00234   /* Reported 20010705 by Alan Bain <alanb@chiark.greenend.org.uk> */
00235   /* Note that IEEE 754 IOP (illegal operation) */
00236   /* = Signaling NAN (SNAN) + operation error (OPERR). */
00237 
00238 #ifdef Can_use__setfpucw /* Has __setfpucw gone missing from S.u.S.E. 6.3? */
00239   __setfpucw(_FPU_IEEE + _FPU_DOUBLE + _FPU_MASK_OPERR + _FPU_MASK_DZ + _FPU_MASK_SNAN + _FPU_MASK_OVFL);
00240 #else
00241   __fpu_control = _FPU_IEEE + _FPU_DOUBLE + _FPU_MASK_OPERR + _FPU_MASK_DZ + _FPU_MASK_SNAN + _FPU_MASK_OVFL;
00242   _FPU_SETCW(__fpu_control);
00243 #endif
00244 
00245 #elif (defined(__powerpc__)||defined(_ARCH_PPC)||defined(_ARCH_PWR)) /* !__mc68k__ */
00246   /* Reported 20011109 by Alan Bain <alanb@chiark.greenend.org.uk> */
00247 
00248 #ifdef Can_use__setfpucw
00249 
00250   /* The following is NOT a mistake -- the author of the fpu_control.h
00251      for the PPC has erroneously defined IEEE mode to turn on exceptions
00252      other than Inexact! Start from default then and turn on only the ones
00253      which we want*/
00254 
00255   __setfpucw(_FPU_DEFAULT +  _FPU_MASK_IM+_FPU_MASK_OM+_FPU_MASK_UM);
00256 
00257 #else /* PPC && !Can_use__setfpucw */
00258 
00259   __fpu_control = _FPU_DEFAULT +_FPU_MASK_OM+_FPU_MASK_IM+_FPU_MASK_UM;
00260   _FPU_SETCW(__fpu_control);
00261 
00262 #endif /*Can_use__setfpucw*/
00263 
00264 #else /* !(mc68000||powerpc) */
00265 
00266 #ifdef _FPU_IEEE
00267 #  ifndef _FPU_EXTENDED /* e.g., ARM processor under Linux */
00268 #  define _FPU_EXTENDED 0
00269 #endif
00270 
00271 #ifndef _FPU_DOUBLE
00272 #  define _FPU_DOUBLE 0
00273 #endif
00274 
00275 #ifdef Can_use__setfpucw /* Has __setfpucw gone missing from S.u.S.E. 6.3? */
00276   __setfpucw(_FPU_IEEE - _FPU_EXTENDED + _FPU_DOUBLE - _FPU_MASK_IM - _FPU_MASK_ZM - _FPU_MASK_OM);
00277 #else
00278   __fpu_control = _FPU_IEEE - _FPU_EXTENDED + _FPU_DOUBLE - _FPU_MASK_IM - _FPU_MASK_ZM - _FPU_MASK_OM;
00279   _FPU_SETCW(__fpu_control);
00280 #endif
00281 
00282 #else /* !_FPU_IEEE */
00283 
00284   TEST_FOR_EXCEPTION(
00285     true, std::logic_error,
00286     "Error, don't know how to trap floating-point errors on this Linux system!"
00287     );
00288 
00289 #endif /* _FPU_IEEE */
00290 
00291 #endif /* __mc68k__ */
00292 
00293 } // ieee0()
00294 
00295 #endif /* __linux__ */
00296 
00297 
00298 //
00299 // Alpha
00300 //
00301 
00302 
00303 #ifdef __alpha
00304 
00305 #ifndef IEEE0_done
00306 
00307 #define IEEE0_done
00308 #include <machine/fpu.h>
00309 
00310 static void ieee0(bool enableTrap)
00311 {
00312   TEST_FOR_EXCEPTION(
00313     enableTrap == false, std::logic_error,
00314     "Error, don't know how to turn off trap for Alpha!"
00315     );
00316   ieee_set_fp_control(IEEE_TRAP_ENABLE_INV);
00317 }
00318 
00319 #endif /*IEEE0_done*/
00320 
00321 #endif /*__alpha*/
00322 
00323 
00324 //
00325 // hpux
00326 //
00327 
00328 
00329 
00330 #ifdef __hpux
00331 
00332 #define IEEE0_done
00333 #define _INCLUDE_HPUX_SOURCE
00334 
00335 #include <cmath>
00336 
00337 #ifndef FP_X_INV
00338 #  include <fenv.h>
00339 #  define fpsetmask fesettrapenable
00340 #  define FP_X_INV FE_INVALID
00341 #endif
00342 
00343 static void ieee0(bool enableTrap)
00344 {
00345   TEST_FOR_EXCEPTION(
00346     enableTrap == false, std::logic_error,
00347     "Error, don't know how to turn off trap for HPUX!"
00348     );
00349   fpsetmask(FP_X_INV);
00350 }
00351 
00352 #endif /*__hpux*/
00353 
00354 
00355 //
00356 // AIX
00357 //
00358 
00359 
00360 #ifdef _AIX
00361 
00362 #define IEEE0_done
00363 #include <fptrap.h>
00364 
00365 static void ieee0(bool enableTrap)
00366 {
00367   TEST_FOR_EXCEPTION(
00368     enableTrap == false, std::logic_error,
00369     "Error, don't know how to turn off trap for AIX!"
00370     );
00371   fp_enable(TRP_INVALID);
00372   fp_trap(FP_TRAP_SYNC);
00373 }
00374 
00375 #endif /*_AIX*/
00376 
00377 
00378 //
00379 // SUN
00380 //
00381 
00382 
00383 #ifdef __sun
00384 
00385 #define IEEE0_done
00386 #include <ieeefp.h>
00387 
00388 static void ieee0(bool enableTrap)
00389 {
00390   TEST_FOR_EXCEPTION(
00391     enableTrap == false, std::logic_error,
00392     "Error, don't know how to turn off trap for SUN!"
00393     );
00394   fpsetmask(FP_X_INV);
00395 }
00396 
00397 #endif // __sun
00398 
00399 
00400 //
00401 // Default (none)
00402 //
00403 
00404 
00405 #ifndef IEEE0_done
00406 
00407 static void ieee0(bool enableTrap)
00408 {
00409   TEST_FOR_EXCEPTION(
00410     true, std::logic_error,
00411     "Error, Don't know how to implement floating-point traps on this platform!"
00412     );
00413 }
00414 
00415 #endif // IEEE0_done

Generated on Tue Oct 20 12:45:26 2009 for Teuchos - Trilinos Tools Package by doxygen 1.4.7