BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/FPU.h
Go to the documentation of this file.
00001 // Copyright (c) 1998-2008  Utrecht University (The Netherlands),
00002 // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany),
00003 // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg
00004 // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria),
00005 // and Tel-Aviv University (Israel).  All rights reserved.
00006 //
00007 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public License as
00009 // published by the Free Software Foundation; version 2.1 of the License.
00010 // See the file LICENSE.LGPL distributed with CGAL.
00011 //
00012 // Licensees holding a valid commercial license may use this file in
00013 // accordance with the commercial license agreement provided with the software.
00014 //
00015 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 //
00018 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Number_types/include/CGAL/FPU.h $
00019 // $Id: FPU.h 47204 2008-12-03 14:43:43Z spion $
00020 //
00021 //
00022 // Author(s)     : Sylvain Pion
00023 
00024 #ifndef CGAL_FPU_H
00025 #define CGAL_FPU_H
00026 
00027 #include <CGAL/number_type_basic.h>
00028 
00029 #ifndef __INTEL_COMPILER
00030 #include <cmath> // for HUGE_VAL
00031 #endif
00032 
00033 // This file specifies some platform dependant functions, regarding the FPU
00034 // directed rounding modes.  There is only support for double precision.
00035 //
00036 // It also contains the definition of the Protect_FPU_rounding<> class,
00037 // which helps to protect blocks of code needing a particular rounding mode.
00038 
00039 #if defined __alpha__  && defined __linux__
00040 extern "C" {
00041 #  include <fenv.h>
00042 }
00043 #elif defined __powerpc__
00044 #  include <fpu_control.h>
00045 #elif defined __SUNPRO_CC && defined __sun
00046 #  include <ieeefp.h>
00047 #elif defined __osf || defined __osf__
00048 #  ifdef __GNUG__
00049      // GCC seems to remove (fixincludes) read_rnd/write_rnd...
00050 #    include "/usr/include/float.h"
00051 #  else
00052 #    include <cfloat>
00053 #  endif
00054 #elif defined _MSC_VER || defined __sparc__ || \
00055      (defined __i386__ && !defined __PGI && !defined __SUNPRO_CC)
00056    // Nothing to include.
00057 #else
00058    // By default we use the ISO C99 version.
00059 #  include <fenv.h>
00060 #endif
00061 
00062 
00063 // Some useful constants
00064 
00065 #if defined CGAL_CFG_NO_LIMITS
00066 #  if defined CGAL_CFG_DENORMALS_COMPILE_BUG
00067      // For compilers crashing when dealing with denormalized values.
00068      // So we have to generate it at run time instead.
00069 #    define CGAL_IA_MIN_DOUBLE (CGAL::CGALi::minimin)
00070 #  else
00071 #    define CGAL_IA_MIN_DOUBLE (5e-324)
00072 #  endif
00073 #  define CGAL_IA_MAX_DOUBLE (1.7976931348623157081e+308)
00074 #else
00075 #  include <limits>
00076 #  define CGAL_IA_MIN_DOUBLE std::numeric_limits<double>::denorm_min()
00077 #  define CGAL_IA_MAX_DOUBLE (std::numeric_limits<double>::max)()
00078 #endif
00079 
00080 
00081 // Pure and safe SSE2 mode (g++ -mfpmath=sse && (-msse2 || -march=pentium4))
00082 // can be detected by :
00083 // TODO : see what Intel and VC++ have to say about this.
00084 #if defined __FLT_EVAL_METHOD__ && defined __SSE2_MATH__ && \
00085       (__FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1)
00086 #  define CGAL_SAFE_SSE2
00087 #  include <xmmintrin.h>
00088 #endif
00089 
00090 // We do not handle -mfpmath=387,sse yet.
00091 #if defined __SSE2_MATH__ && \
00092     ! (__FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1)
00093 #  warning Unsafe SSE2 mode : not supported yet.
00094 #endif
00095 
00096 // The CGAL_FPU_HAS_EXCESS_PRECISION macro is defined if some computations with
00097 // double can use more than the 53bits of precision of IEEE754, and/or if the
00098 // exponent has a wider range.  This can produce double rounding effects and
00099 // other bad things that we need to protect against.
00100 // The typical offender is the traditional FPU of x86 (SSE2-only mode is not affected).
00101 // Are there others?
00102 #if (defined __i386__ && !defined CGAL_SAFE_SSE2) || defined _MSC_VER
00103 #  define CGAL_FPU_HAS_EXCESS_PRECISION
00104 #endif
00105 
00106 CGAL_BEGIN_NAMESPACE
00107 
00108 namespace CGALi {
00109 
00110 #ifdef CGAL_CFG_DENORMALS_COMPILE_BUG
00111 extern double minimin;
00112 #endif
00113 
00114 #ifdef __INTEL_COMPILER
00115 const double infinity = std::numeric_limits<double>::infinity();
00116 #else
00117 const double infinity = HUGE_VAL;
00118 #endif
00119 
00120 } // namespace CGALi
00121 
00122 
00123 // Inline function to stop compiler optimization.
00124 inline double IA_force_to_double(double x)
00125 {
00126 #if defined __GNUG__ && !defined __INTEL_COMPILER
00127   // Intel does not emulate GCC perfectly...
00128   asm("" : "=m"(x) : "m"(x));
00129   // asm("" : "+m"(x) );
00130   return x;
00131 #else
00132   volatile double e = x;
00133   return e;
00134 #endif
00135 }
00136 
00137 // Interval arithmetic needs to protect against double-rounding effects
00138 // caused by excess FPU precision, even if it forces the 53bit mantissa
00139 // precision, because there is no way to fix the problem for the exponent
00140 // which has the same problem.  This affects underflow and overflow cases.
00141 // In case one does not care about such "extreme" situations, one can
00142 // set CGAL_IA_NO_X86_OVER_UNDER_FLOW_PROTECT.
00143 #if defined CGAL_FPU_HAS_EXCESS_PRECISION && \
00144    !defined CGAL_IA_NO_X86_OVER_UNDER_FLOW_PROTECT
00145 #  define CGAL_IA_FORCE_TO_DOUBLE(x) CGAL::IA_force_to_double(x)
00146 #else
00147 #  define CGAL_IA_FORCE_TO_DOUBLE(x) (x)
00148 #endif
00149 
00150 // We sometimes need to stop constant propagation,
00151 // because operations are done with a wrong rounding mode at compile time.
00152 #ifndef CGAL_IA_DONT_STOP_CONSTANT_PROPAGATION
00153 #  define CGAL_IA_STOP_CPROP(x)    CGAL::IA_force_to_double(x)
00154 #else
00155 #  define CGAL_IA_STOP_CPROP(x)    (x)
00156 #endif
00157 
00158 // std::sqrt(double) on VC++ and CygWin is buggy when not optimizing.
00159 #if defined ( _MSC_VER ) && ! defined ( _WIN64 )
00160 inline double IA_bug_sqrt(double d)
00161 {
00162   _asm
00163   {
00164     fld d
00165     fsqrt
00166     fstp d
00167   }
00168   return d;
00169 }
00170 
00171 #  define CGAL_BUG_SQRT(d) IA_bug_sqrt(d)
00172 
00173 
00174 #elif defined __SSE2_MATH__
00175 // For SSE2, we need to call __builtin_sqrt() instead of libc's sqrt().
00176 #  define CGAL_BUG_SQRT(d) __builtin_sqrt(d)
00177 #elif defined __CYGWIN__
00178 inline double IA_bug_sqrt(double d)
00179 {
00180   double r;
00181   asm volatile ("fsqrt" : "=t"(r) : "0"(d));
00182   return r;
00183 }
00184 #  define CGAL_BUG_SQRT(d) IA_bug_sqrt(d)
00185 #else
00186 #  define CGAL_BUG_SQRT(d) std::sqrt(d)
00187 #endif
00188 
00189 // Here are the operator macros that make use of the above.
00190 // With GCC, we can do slightly better : test with __builtin_constant_p()
00191 // that both arguments are constant before stopping one of them.
00192 // Use inline functions instead ?
00193 #define CGAL_IA_ADD(a,b) CGAL_IA_FORCE_TO_DOUBLE((a)+CGAL_IA_STOP_CPROP(b))
00194 #define CGAL_IA_SUB(a,b) CGAL_IA_FORCE_TO_DOUBLE((a)-CGAL_IA_STOP_CPROP(b))
00195 #define CGAL_IA_MUL(a,b) CGAL_IA_FORCE_TO_DOUBLE((a)*CGAL_IA_STOP_CPROP(b))
00196 #define CGAL_IA_DIV(a,b) CGAL_IA_FORCE_TO_DOUBLE((a)/CGAL_IA_STOP_CPROP(b))
00197 #define CGAL_IA_SQUARE(a) CGAL_IA_MUL(a,a)
00198 #define CGAL_IA_SQRT(a) \
00199         CGAL_IA_FORCE_TO_DOUBLE(CGAL_BUG_SQRT(CGAL_IA_STOP_CPROP(a)))
00200 
00201 
00202 #if defined __i386__ && !defined __PGI && !defined __SUNPRO_CC
00203 
00204 #  if defined CGAL_SAFE_SSE2
00205 
00206 #define CGAL_IA_SETFPCW(CW) _MM_SET_ROUNDING_MODE(CW)
00207 #define CGAL_IA_GETFPCW(CW) CW = _MM_GET_ROUNDING_MODE()
00208 typedef unsigned int FPU_CW_t;
00209 #define CGAL_FE_TONEAREST    _MM_ROUND_NEAREST
00210 #define CGAL_FE_TOWARDZERO   _MM_ROUND_TOWARD_ZERO
00211 #define CGAL_FE_UPWARD       _MM_ROUND_UP
00212 #define CGAL_FE_DOWNWARD     _MM_ROUND_DOWN
00213 
00214 #  else
00215 // The GNU libc version (cf powerpc) is nicer, but doesn't work on libc 5 :(
00216 // This one also works with CygWin.
00217 // Note that the ISO C99 version may not be enough because of the extended
00218 // mantissa issue on x86 (may be required by some kinds of computation, but
00219 // as far as CGAL::Interval_nt<> is concerned, the double-rounding issues
00220 // are taking care of there).
00221 #define CGAL_IA_SETFPCW(CW) asm volatile ("fldcw %0" : :"m" (CW))
00222 #define CGAL_IA_GETFPCW(CW) asm volatile ("fnstcw %0" : "=m" (CW))
00223 typedef unsigned short FPU_CW_t;
00224 #define CGAL_FE_TONEAREST    (0x000 | 0x127f)
00225 #define CGAL_FE_TOWARDZERO   (0xc00 | 0x127f)
00226 #define CGAL_FE_UPWARD       (0x800 | 0x127f)
00227 #define CGAL_FE_DOWNWARD     (0x400 | 0x127f)
00228 
00229 #  endif
00230 
00231 #elif defined __powerpc__
00232 #define CGAL_IA_SETFPCW(CW) _FPU_SETCW(CW)
00233 #define CGAL_IA_GETFPCW(CW) _FPU_GETCW(CW)
00234 typedef fpu_control_t FPU_CW_t;
00235 #define CGAL_FE_TONEAREST    (_FPU_RC_NEAREST | _FPU_DEFAULT)
00236 #define CGAL_FE_TOWARDZERO   (_FPU_RC_ZERO    | _FPU_DEFAULT)
00237 #define CGAL_FE_UPWARD       (_FPU_RC_UP      | _FPU_DEFAULT)
00238 #define CGAL_FE_DOWNWARD     (_FPU_RC_DOWN    | _FPU_DEFAULT)
00239 
00240 #elif defined __SUNPRO_CC && defined __sun
00241 #define CGAL_IA_SETFPCW(CW) fpsetround(fp_rnd(CW))
00242 #define CGAL_IA_GETFPCW(CW) CW = fpgetround()
00243 typedef unsigned int FPU_CW_t;
00244 #define CGAL_FE_TONEAREST    FP_RN
00245 #define CGAL_FE_TOWARDZERO   FP_RZ
00246 #define CGAL_FE_UPWARD       FP_RP
00247 #define CGAL_FE_DOWNWARD     FP_RM
00248 
00249 #elif defined __sparc__
00250 #define CGAL_IA_SETFPCW(CW) asm volatile ("ld %0,%%fsr" : :"m" (CW))
00251 #define CGAL_IA_GETFPCW(CW) asm volatile ("st %%fsr,%0" : "=m" (CW))
00252 typedef unsigned int FPU_CW_t;
00253 #define CGAL_FE_TONEAREST    (0x0        | 0x20000000 | 0x1f)
00254 #define CGAL_FE_TOWARDZERO   (0x40000000 | 0x20000000 | 0x1f)
00255 #define CGAL_FE_UPWARD       (0x80000000 | 0x20000000 | 0x1f)
00256 #define CGAL_FE_DOWNWARD     (0xc0000000 | 0x20000000 | 0x1f)
00257 
00258 #elif defined __mips__
00259 #define CGAL_IA_SETFPCW(CW) asm volatile ("ctc1 %0,$31" : :"r" (CW))
00260 #define CGAL_IA_GETFPCW(CW) asm volatile ("cfc1 %0,$31" : "=r" (CW))
00261 typedef unsigned int FPU_CW_t;
00262 #define CGAL_FE_TONEAREST    (0x0)
00263 #define CGAL_FE_TOWARDZERO   (0x1)
00264 #define CGAL_FE_UPWARD       (0x2)
00265 #define CGAL_FE_DOWNWARD     (0x3)
00266 
00267 #elif defined __osf || defined __osf__  // Not yet supported.
00268 #define CGAL_IA_SETFPCW(CW) write_rnd(CW)
00269 #define CGAL_IA_GETFPCW(CW) CW = read_rnd()
00270 typedef unsigned int FPU_CW_t;
00271 #define CGAL_FE_TONEAREST    FP_RND_RN
00272 #define CGAL_FE_TOWARDZERO   FP_RND_RZ
00273 #define CGAL_FE_UPWARD       FP_RND_RP
00274 #define CGAL_FE_DOWNWARD     FP_RND_RM
00275 
00276 #elif defined ( _MSC_VER )
00277 #if ( _MSC_VER < 1400)
00278 #define CGAL_IA_SETFPCW(CW) _controlfp (CW, _MCW_RC )
00279 #define CGAL_IA_GETFPCW(CW) CW = _controlfp (0, 0 ) &  _MCW_RC
00280 typedef unsigned short FPU_CW_t;
00281 #else
00282 #define CGAL_IA_SETFPCW(CW) unsigned int dummy; _controlfp_s (&dummy, CW, _MCW_RC )
00283 #define CGAL_IA_GETFPCW(CW)_controlfp_s (&CW, 0, 0 ); CW  &=  _MCW_RC
00284 typedef unsigned int FPU_CW_t;
00285 #endif
00286 
00287 #define CGAL_FE_TONEAREST    _RC_NEAR
00288 #define CGAL_FE_TOWARDZERO   _RC_CHOP
00289 #define CGAL_FE_UPWARD       _RC_UP
00290 #define CGAL_FE_DOWNWARD     _RC_DOWN
00291 
00292 #else
00293 // This is a version following the ISO C99 standard, which aims at portability.
00294 // The drawbacks are speed on one hand, and also, on x86, it doesn't fix the
00295 // extended mantissa issue (this is not a problem for IA, but it is one for
00296 // some future modular computations).
00297 #define CGAL_IA_SETFPCW(CW)  fesetround(CW)
00298 #define CGAL_IA_GETFPCW(CW)  CW = fegetround()
00299 typedef int FPU_CW_t;
00300 #define CGAL_FE_TONEAREST    FE_TONEAREST
00301 #define CGAL_FE_TOWARDZERO   FE_TOWARDZERO
00302 #define CGAL_FE_UPWARD       FE_UPWARD
00303 #define CGAL_FE_DOWNWARD     FE_DOWNWARD
00304 #endif
00305 
00306 // User interface:
00307 
00308 inline
00309 FPU_CW_t
00310 FPU_get_cw (void)
00311 {
00312     FPU_CW_t cw;
00313     CGAL_IA_GETFPCW(cw);
00314     return cw;
00315 }
00316 
00317 inline
00318 void
00319 FPU_set_cw (FPU_CW_t cw)
00320 {
00321     CGAL_IA_SETFPCW(cw);
00322 }
00323 
00324 inline
00325 FPU_CW_t
00326 FPU_get_and_set_cw (FPU_CW_t cw)
00327 {
00328     FPU_CW_t old = FPU_get_cw();
00329     FPU_set_cw(cw);
00330     return old;
00331 }
00332 
00333 
00334 // A class whose constructor sets the FPU mode to +inf, saves a backup of it,
00335 // and whose destructor resets it back to the saved state.
00336 
00337 template <bool Protected = true> struct Protect_FPU_rounding;
00338 
00339 template <>
00340 struct Protect_FPU_rounding<true>
00341 {
00342   Protect_FPU_rounding(FPU_CW_t r = CGAL_FE_UPWARD)
00343     : backup( FPU_get_and_set_cw(r) ) {}
00344 
00345   ~Protect_FPU_rounding()
00346   {
00347      FPU_set_cw(backup);
00348   }
00349 
00350 private:
00351   FPU_CW_t backup;
00352 };
00353 
00354 template <>
00355 struct Protect_FPU_rounding<false>
00356 {
00357   Protect_FPU_rounding() {}
00358   Protect_FPU_rounding(FPU_CW_t /*= CGAL_FE_UPWARD*/) {}
00359 };
00360 
00361 
00362 // A wrapper on top of the Protect_FPU_rounding to add "expensive" checks
00363 // of the rounding mode.  It is used internally, to benefit from the
00364 // protector declarations to add checks in non-protected mode.
00365 
00366 template <bool Protected = true>
00367 struct Checked_protect_FPU_rounding
00368   : Protect_FPU_rounding<Protected>
00369 {
00370   Checked_protect_FPU_rounding()
00371   {
00372     CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_UPWARD);
00373   }
00374 
00375   Checked_protect_FPU_rounding(FPU_CW_t r)
00376     : Protect_FPU_rounding<Protected>(r)
00377   {
00378     CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_UPWARD);
00379   }
00380 };
00381 
00382 
00383 // The class Set_ieee_double_precision forces the double precision (53bit mantissa),
00384 // to protect from double rounding effects on x86 FPU.
00385 // ( Note that it also sets the rounding mode to nearest. )
00386 // Its destructor restores the FPU state as it was previously.
00387 // Note that this affects "long double" as well, and other potential side effects.
00388 // And note that it does not (cannot) "fix" the same problem for the exponent.
00389 
00390 struct Set_ieee_double_precision
00391 #ifdef CGAL_FPU_HAS_EXCESS_PRECISION
00392   : public Protect_FPU_rounding<>
00393 {
00394   Set_ieee_double_precision()
00395     : Protect_FPU_rounding<>(CGAL_FE_TONEAREST) {}
00396 };
00397 #else
00398 {
00399   Set_ieee_double_precision() {} // only to kill compiler warnings.
00400 };
00401 #endif
00402 
00403 
00404 // The following function serves the same goal as Set_ieee_double_precision but
00405 // does the change globally (no destructor resets the previous behavior).
00406 inline void force_ieee_double_precision()
00407 {
00408 #ifdef CGAL_FPU_HAS_EXCESS_PRECISION
00409     FPU_set_cw(CGAL_FE_TONEAREST);
00410 #endif
00411 }
00412 
00413 CGAL_END_NAMESPACE
00414 
00415 #endif // CGAL_FPU_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines