/usr/include/CGAL/FPU.h is in libcgal-dev 4.11-2build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 | // Copyright (c) 1998-2008
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Sylvain Pion
#ifndef CGAL_FPU_H
#define CGAL_FPU_H
#include <CGAL/assertions.h>
#include <CGAL/use.h>
#ifndef __INTEL_COMPILER
#include <cmath> // for HUGE_VAL
#endif
// This file specifies some platform dependant functions, regarding the FPU
// directed rounding modes. There is only support for double precision.
//
// It also contains the definition of the Protect_FPU_rounding<> class,
// which helps to protect blocks of code needing a particular rounding mode.
#if defined __alpha__ && defined __linux__
extern "C" {
# include <fenv.h>
}
#elif defined __SUNPRO_CC && defined __sun
# include <ieeefp.h>
#elif defined __osf || defined __osf__
# ifdef __GNUG__
// GCC seems to remove (fixincludes) read_rnd/write_rnd...
# include "/usr/include/float.h"
# else
# include <cfloat>
# endif
#elif defined _MSC_VER || defined __sparc__ || \
(defined __i386__ && !defined __PGI && !defined __SUNPRO_CC \
&& !defined __SSE2__)
// Nothing to include.
#else
// By default we use the ISO C99 version.
# include <fenv.h>
#endif
// Some useful constants
#if defined CGAL_CFG_NO_LIMITS
# if defined CGAL_CFG_DENORMALS_COMPILE_BUG
// For compilers crashing when dealing with denormalized values.
// So we have to generate it at run time instead.
# define CGAL_IA_MIN_DOUBLE (CGAL::internal::get_static_minimin())
# else
# define CGAL_IA_MIN_DOUBLE (5e-324)
# endif
# define CGAL_IA_MAX_DOUBLE (1.7976931348623157081e+308)
#else
# include <limits>
# define CGAL_IA_MIN_DOUBLE std::numeric_limits<double>::denorm_min()
# define CGAL_IA_MAX_DOUBLE (std::numeric_limits<double>::max)()
#endif
// Pure and safe SSE2 mode (g++ -mfpmath=sse && (-msse2 || -march=pentium4))
// can be detected by :
// TODO : see what Intel and VC++ have to say about this.
#if defined __FLT_EVAL_METHOD__ && defined __SSE2_MATH__ && \
(__FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1)
# define CGAL_SAFE_SSE2
# include <xmmintrin.h>
#endif
// The CGAL_FPU_HAS_EXCESS_PRECISION macro is defined if some computations with
// double can use more than the 53bits of precision of IEEE754, and/or if the
// exponent has a wider range. This can produce double rounding effects and
// other bad things that we need to protect against.
// The typical offender is the traditional FPU of x86 (SSE2-only mode is not affected).
// Are there others, besides itanium and m68k?
#if !defined CGAL_IA_NO_X86_OVER_UNDER_FLOW_PROTECT && \
(((defined __i386__ || defined __x86_64__) && !defined CGAL_SAFE_SSE2) \
|| defined __ia64__ \
|| defined _M_IX86 || defined _M_X64 || defined _M_IA64 \
|| (defined FLT_EVAL_METHOD && FLT_EVAL_METHOD != 0 && FLT_EVAL_METHOD != 1))
# define CGAL_FPU_HAS_EXCESS_PRECISION
#endif
// Presence of SSE2 (for explicit use)
#if defined(__SSE2__) \
|| (defined(_M_IX86_FP) && _M_IX86_FP >= 2) \
|| defined(_M_X64)
# include <emmintrin.h>
# define CGAL_HAS_SSE2 1
#endif
// Only define CGAL_USE_SSE2 for 64 bits where malloc has a suitable
// alignment, 32 bits is too dangerous.
#if defined(CGAL_HAS_SSE2) && (defined(__x86_64__) || defined(_M_X64))
# define CGAL_USE_SSE2 1
#endif
#ifdef CGAL_CFG_DENORMALS_COMPILE_BUG
double& get_static_minimin(); // Defined in Interval_arithmetic_impl.h
#endif
namespace CGAL {
namespace internal {
#ifdef __INTEL_COMPILER
const double infinity = std::numeric_limits<double>::infinity();
#else
const double infinity = HUGE_VAL;
#endif
} // namespace internal
#ifdef CGAL_HEADER_ONLY
// Defined in test_FPU_rounding_mode_impl.h
struct Check_FPU_rounding_mode_is_restored;
inline const Check_FPU_rounding_mode_is_restored&
get_static_check_fpu_rounding_mode_is_restored();
#endif
// Inline function to stop compiler optimizations that shouldn't happen with
// pragma fenv on.
// - constant propagation
// - migration of fesetround across floating point operations
// - (-a)-b -> -(a+b)
// - (-a)*b -> -(a*b)
// etc
inline double IA_opacify(double x)
{
#ifdef __llvm__
// LLVM's support for inline asm is completely messed up:
// http://llvm.org/bugs/show_bug.cgi?id=17958
// http://llvm.org/bugs/show_bug.cgi?id=17959
// etc.
// This seems to produce code that is ok (not optimal but better than
// volatile). In case of trouble, use volatile instead.
# ifdef CGAL_HAS_SSE2
asm volatile ("" : "+x"(x) );
# elif (defined __VFP_FP__ && !defined __SOFTFP__) || defined __aarch64__
// ARM
asm volatile ("" : "+w"(x) );
# else
asm volatile ("" : "+m"(x) );
# endif
return x;
#elif defined __xlC__
// PowerPC - XL C++ (the z/OS version supposedly does not define this macro)
// If we give it an alternative "+fm", it gets confused and generates worse code.
asm volatile ("" : "+f"(x) );
return x;
#elif defined __GNUG__
// Intel used not to emulate this perfectly, we'll see.
// If we create a version of IA_opacify for vectors, note that gcc < 4.8
// fails with "+g" and we need to use "+mx" instead.
// "+X" ICEs ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59155 ) and
// may not be safe?
// The constraint 'g' doesn't include floating point registers ???
// Intel has a bug where -mno-sse still defines __SSE__ and __SSE2__
// (-mno-sse2 works though), no work-around for now.
# if defined __SSE2_MATH__ || (defined __INTEL_COMPILER && defined __SSE2__)
# if __GNUC__ * 100 + __GNUC_MINOR__ >= 409
// ICEs in reload/LRA with older versions.
asm volatile ("" : "+gx"(x) );
# else
asm volatile ("" : "+mx"(x) );
# endif
# elif (defined __i386__ || defined __x86_64__)
// "+f" doesn't compile on x86(_64)
// ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59157 )
// Don't mix "t" with "g": http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59180
// We can't put "t" with "x" either, prefer "x" for -mfpmath=sse,387.
// ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59181 )
asm volatile ("" : "+mt"(x) );
# elif (defined __VFP_FP__ && !defined __SOFTFP__) || defined __aarch64__
// ARM
asm volatile ("" : "+gw"(x) );
# elif defined __powerpc__ || defined __POWERPC__
// PowerPC
asm volatile ("" : "+gd"(x) );
# elif defined __sparc
// Sparc
asm volatile ("" : "+ge"(x) );
# elif defined __ia64
// Itanium
asm volatile ("" : "+gf"(x) );
# else
asm volatile ("" : "+g"(x) );
# endif
return x;
#else
volatile double e = x;
return e;
#endif
}
// Inline function to drop excess precision before we forget the rounding mode,
// and stop compiler optimizations at the same time.
inline double IA_force_to_double(double x)
{
#ifndef CGAL_FPU_HAS_EXCESS_PRECISION
return IA_opacify (x);
#else
#if defined __GNUG__
# ifdef CGAL_HAS_SSE2
// For an explanation of volatile:
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56027
asm volatile ("" : "+mx"(x) );
# else
// Similar to writing to a volatile and reading back, except that calling
// it k times in a row only goes through memory once.
asm volatile ("" : "+m"(x) );
# endif
return x;
#else
volatile double e = x;
return e;
#endif
#endif
}
// Interval arithmetic needs to protect against double-rounding effects
// caused by excess FPU precision, even if it forces the 53bit mantissa
// precision, because there is no way to fix the problem for the exponent
// which has the same problem. This affects underflow and overflow cases.
// In case one does not care about such "extreme" situations, one can
// set CGAL_IA_NO_X86_OVER_UNDER_FLOW_PROTECT to pretend there is no excess
// precision.
#if defined CGAL_FPU_HAS_EXCESS_PRECISION
# define CGAL_IA_FORCE_TO_DOUBLE(x) CGAL::IA_force_to_double(x)
#elif 1
// LLVM doesn't have -frounding-math so needs extra protection.
// GCC also migrates fesetround calls over FP instructions, so protect
// everyone.
# define CGAL_IA_FORCE_TO_DOUBLE(x) CGAL::IA_opacify(x)
#else
// Unused, reserved to compilers without excess precision and pragma fenv on.
// ??? Should we trust Visual Studio not to optimize too much and let it use
// this when CGAL_IA_NO_X86_OVER_UNDER_FLOW_PROTECT?
# define CGAL_IA_FORCE_TO_DOUBLE(x) (x)
#endif
// We sometimes need to stop constant propagation,
// because operations are done with a wrong rounding mode at compile time.
#ifndef CGAL_IA_DONT_STOP_CONSTANT_PROPAGATION
# define CGAL_IA_STOP_CPROP(x) CGAL::IA_opacify(x)
#else
# define CGAL_IA_STOP_CPROP(x) (x)
#endif
// std::sqrt(double) on VC++ and CygWin is buggy when not optimizing.
#if defined ( _MSC_VER ) && ! defined ( _WIN64 )
inline double IA_bug_sqrt(double d)
{
_asm
{
fld d
fsqrt
fstp d
}
return d;
}
# define CGAL_BUG_SQRT(d) IA_bug_sqrt(d)
#elif defined __SSE2_MATH__
// For SSE2, we need to call __builtin_sqrt() instead of libc's sqrt().
# define CGAL_BUG_SQRT(d) __builtin_sqrt(d)
#elif defined __CYGWIN__
inline double IA_bug_sqrt(double d)
{
double r;
asm volatile ("fsqrt" : "=t"(r) : "0"(d));
return r;
}
# define CGAL_BUG_SQRT(d) IA_bug_sqrt(d)
#else
# define CGAL_BUG_SQRT(d) std::sqrt(d)
#endif
// Here are the operator macros that make use of the above.
// With GCC, we can do slightly better : test with __builtin_constant_p()
// that both arguments are constant before stopping one of them.
// Use inline functions instead ?
#define CGAL_IA_ADD(a,b) CGAL_IA_FORCE_TO_DOUBLE((a)+CGAL_IA_STOP_CPROP(b))
#define CGAL_IA_SUB(a,b) CGAL_IA_FORCE_TO_DOUBLE(CGAL_IA_STOP_CPROP(a)-(b))
#define CGAL_IA_MUL(a,b) CGAL_IA_FORCE_TO_DOUBLE((a)*CGAL_IA_STOP_CPROP(b))
#define CGAL_IA_DIV(a,b) CGAL_IA_FORCE_TO_DOUBLE((a)/CGAL_IA_STOP_CPROP(b))
#define CGAL_IA_SQUARE(a) CGAL_IA_MUL(a,a)
#define CGAL_IA_SQRT(a) \
CGAL_IA_FORCE_TO_DOUBLE(CGAL_BUG_SQRT(CGAL_IA_STOP_CPROP(a)))
#if defined CGAL_SAFE_SSE2
#define CGAL_IA_SETFPCW(CW) _MM_SET_ROUNDING_MODE(CW)
#define CGAL_IA_GETFPCW(CW) CW = _MM_GET_ROUNDING_MODE()
typedef unsigned int FPU_CW_t;
#define CGAL_FE_TONEAREST _MM_ROUND_NEAREST
#define CGAL_FE_TOWARDZERO _MM_ROUND_TOWARD_ZERO
#define CGAL_FE_UPWARD _MM_ROUND_UP
#define CGAL_FE_DOWNWARD _MM_ROUND_DOWN
#elif defined __i386__ && !defined __PGI && !defined __SUNPRO_CC \
&& !defined CGAL_HAS_SSE2
// If we use both 387 and sse2, be safe and drop to fe[gs]etround.
// Can we test CGAL_USE_SSE2 instead?
// The GNU libc version (cf powerpc) is nicer, but doesn't work on libc 5 :(
// This one also works with CygWin.
// Note that the ISO C99 version may not be enough because of the extended
// mantissa issue on x86 (may be required by some kinds of computation, but
// as far as CGAL::Interval_nt<> is concerned, the double-rounding issues
// are taking care of there).
#define CGAL_IA_SETFPCW(CW) asm volatile ("fldcw %0" : :"m" (CW))
#define CGAL_IA_GETFPCW(CW) asm volatile ("fnstcw %0" : "=m" (CW))
typedef unsigned short FPU_CW_t;
#define CGAL_FE_TONEAREST (0x000 | 0x127f)
#define CGAL_FE_TOWARDZERO (0xc00 | 0x127f)
#define CGAL_FE_UPWARD (0x800 | 0x127f)
#define CGAL_FE_DOWNWARD (0x400 | 0x127f)
#elif defined __SUNPRO_CC && defined __sun
#define CGAL_IA_SETFPCW(CW) fpsetround(fp_rnd(CW))
#define CGAL_IA_GETFPCW(CW) CW = fpgetround()
typedef unsigned int FPU_CW_t;
#define CGAL_FE_TONEAREST FP_RN
#define CGAL_FE_TOWARDZERO FP_RZ
#define CGAL_FE_UPWARD FP_RP
#define CGAL_FE_DOWNWARD FP_RM
#elif defined __sparc__
#define CGAL_IA_SETFPCW(CW) asm volatile ("ld %0,%%fsr" : :"m" (CW))
#define CGAL_IA_GETFPCW(CW) asm volatile ("st %%fsr,%0" : "=m" (CW))
typedef unsigned int FPU_CW_t;
#define CGAL_FE_TONEAREST (0x0 | 0x20000000 | 0x1f)
#define CGAL_FE_TOWARDZERO (0x40000000 | 0x20000000 | 0x1f)
#define CGAL_FE_UPWARD (0x80000000 | 0x20000000 | 0x1f)
#define CGAL_FE_DOWNWARD (0xc0000000 | 0x20000000 | 0x1f)
#elif defined __mips__
#define CGAL_IA_SETFPCW(CW) asm volatile ("ctc1 %0,$31" : :"r" (CW))
#define CGAL_IA_GETFPCW(CW) asm volatile ("cfc1 %0,$31" : "=r" (CW))
typedef unsigned int FPU_CW_t;
#define CGAL_FE_TONEAREST (0x0)
#define CGAL_FE_TOWARDZERO (0x1)
#define CGAL_FE_UPWARD (0x2)
#define CGAL_FE_DOWNWARD (0x3)
#elif defined __osf || defined __osf__ // Not yet supported.
#define CGAL_IA_SETFPCW(CW) write_rnd(CW)
#define CGAL_IA_GETFPCW(CW) CW = read_rnd()
typedef unsigned int FPU_CW_t;
#define CGAL_FE_TONEAREST FP_RND_RN
#define CGAL_FE_TOWARDZERO FP_RND_RZ
#define CGAL_FE_UPWARD FP_RND_RP
#define CGAL_FE_DOWNWARD FP_RND_RM
#elif defined ( _MSC_VER )
#if ( _MSC_VER < 1400)
#define CGAL_IA_SETFPCW(CW) _controlfp (CW, _MCW_RC )
#define CGAL_IA_GETFPCW(CW) CW = _controlfp (0, 0 ) & _MCW_RC
typedef unsigned short FPU_CW_t;
#else
#define CGAL_IA_SETFPCW(CW) unsigned int dummy; _controlfp_s (&dummy, CW, _MCW_RC )
#define CGAL_IA_GETFPCW(CW)_controlfp_s (&CW, 0, 0 ); CW &= _MCW_RC
typedef unsigned int FPU_CW_t;
#endif
#define CGAL_FE_TONEAREST _RC_NEAR
#define CGAL_FE_TOWARDZERO _RC_CHOP
#define CGAL_FE_UPWARD _RC_UP
#define CGAL_FE_DOWNWARD _RC_DOWN
#else
// This is a version following the ISO C99 standard, which aims at portability.
// The drawbacks are speed on one hand, and also, on x86, it doesn't fix the
// extended mantissa issue (this is not a problem for IA, but it is one for
// some future modular computations).
#define CGAL_IA_SETFPCW(CW) fesetround(CW)
#define CGAL_IA_GETFPCW(CW) CW = fegetround()
typedef int FPU_CW_t;
#define CGAL_FE_TONEAREST FE_TONEAREST
#define CGAL_FE_TOWARDZERO FE_TOWARDZERO
#define CGAL_FE_UPWARD FE_UPWARD
#define CGAL_FE_DOWNWARD FE_DOWNWARD
#endif
// User interface:
inline
FPU_CW_t
FPU_get_cw (void)
{
FPU_CW_t cw;
CGAL_IA_GETFPCW(cw);
return cw;
}
// User interface (cont):
inline
void
FPU_set_cw (FPU_CW_t cw)
{
CGAL_IA_SETFPCW(cw);
}
inline
FPU_CW_t
FPU_get_and_set_cw (FPU_CW_t cw)
{
FPU_CW_t old = FPU_get_cw();
FPU_set_cw(cw);
return old;
}
// A class whose constructor sets the FPU mode to +inf, saves a backup of it,
// and whose destructor resets it back to the saved state.
template <bool Protected = true> struct Protect_FPU_rounding;
template <>
struct Protect_FPU_rounding<true>
{
Protect_FPU_rounding(FPU_CW_t r = CGAL_FE_UPWARD)
: backup( FPU_get_and_set_cw(r) ) {}
~Protect_FPU_rounding()
{
FPU_set_cw(backup);
}
private:
FPU_CW_t backup;
};
template <>
struct Protect_FPU_rounding<false>
{
Protect_FPU_rounding() {}
Protect_FPU_rounding(FPU_CW_t /*= CGAL_FE_UPWARD*/) {}
};
// A wrapper on top of the Protect_FPU_rounding to add "expensive" checks
// of the rounding mode. It is used internally, to benefit from the
// protector declarations to add checks in non-protected mode.
template <bool Protected = true>
struct Checked_protect_FPU_rounding
: Protect_FPU_rounding<Protected>
{
Checked_protect_FPU_rounding()
{
CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_UPWARD);
}
Checked_protect_FPU_rounding(FPU_CW_t r)
: Protect_FPU_rounding<Protected>(r)
{
CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_UPWARD);
}
};
// The class Set_ieee_double_precision forces the double precision (53bit mantissa),
// to protect from double rounding effects on x86 FPU.
// ( Note that it also sets the rounding mode to nearest. )
// Its destructor restores the FPU state as it was previously.
// Note that this affects "long double" as well, and other potential side effects.
// And note that it does not (cannot) "fix" the same problem for the exponent.
struct Set_ieee_double_precision
#ifdef CGAL_FPU_HAS_EXCESS_PRECISION
: public Protect_FPU_rounding<>
{
Set_ieee_double_precision()
: Protect_FPU_rounding<>(CGAL_FE_TONEAREST) {}
};
#else
{
Set_ieee_double_precision() {} // only to kill compiler warnings.
};
#endif
// The following function serves the same goal as Set_ieee_double_precision but
// does the change globally (no destructor resets the previous behavior).
inline void force_ieee_double_precision()
{
#ifdef CGAL_FPU_HAS_EXCESS_PRECISION
FPU_set_cw(CGAL_FE_TONEAREST);
#endif
}
} //namespace CGAL
#ifdef CGAL_HEADER_ONLY
#include <CGAL/test_FPU_rounding_mode_impl.h>
#endif // CGAL_HEADER_ONLY
#endif // CGAL_FPU_H
|