BWAPI
|
00001 /**************************************************************************** 00002 * Core Library Version 1.7, August 2004 00003 * Copyright (c) 1995-2004 Exact Computation Project 00004 * All rights reserved. 00005 * 00006 * This file is part of CORE (http://cs.nyu.edu/exact/core/); you may 00007 * redistribute it under the terms of the Q Public License version 1.0. 00008 * See the file LICENSE.QPL distributed with CORE. 00009 * 00010 * Licensees holding a valid commercial license may use this file in 00011 * accordance with the commercial license agreement provided with the 00012 * software. 00013 * 00014 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00015 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00016 * 00017 * 00018 * File: Filter.h 00019 * Synopsis: 00020 * This is a simple filtered floating point number, 00021 * represented by the main class, FilterFp. 00022 * based on the Burnikel-Funke-Schirra (BFS) filter scheme. 00023 * We do not use IEEE exception mechanism here. 00024 * It is used by the Expr class. 00025 * 00026 * Written by 00027 * Zilin Du <zilin@cs.nyu.edu> 00028 * Chee Yap <yap@cs.nyu.edu> 00029 * 00030 * WWW URL: http://cs.nyu.edu/exact/ 00031 * Email: exact@cs.nyu.edu 00032 * 00033 * $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Core/include/CGAL/CORE/Filter.h $ 00034 * $Id: Filter.h 45042 2008-08-20 11:14:00Z spion $ 00035 ***************************************************************************/ 00036 00037 #ifndef _CORE_FILTER_H_ 00038 #define _CORE_FILTER_H_ 00039 00040 #include <CGAL/config.h> 00041 #include <CGAL/CORE/Real.h> 00042 #include <cmath> 00043 00044 #if !defined CGAL_CFG_NO_CPP0X_ISFINITE 00045 #define finite(x) std::isfinite(x) 00046 #elif defined (_MSC_VER) || defined (__MINGW32__) // add support for MinGW 00047 #define finite(x) _finite(x) 00048 #define ilogb(x) (int)_logb(x) 00049 #endif 00050 00051 #if defined(sun) || defined(__sun) 00052 #include <ieeefp.h> 00053 #endif 00054 00055 CORE_BEGIN_NAMESPACE 00056 00057 const int POWTWO_26 = (1 << 26); 00058 00062 class filteredFp { 00063 double fpVal; // approximate double value for some "real value" 00064 double maxAbs; // if (|fpVal| > maxAbs * ind * 2^{-53}) then 00065 int ind; // sign of value is sign(fpVal). Else, don't know. 00066 // REFERENCE: Burnikel, Funke, Schirra (BFS) filter 00067 // Chee: in isOK(), you used the test "|fpVal| >= maxAbs * ind * 2^{-53}" 00068 // which seems to be correct (i.e., not |fpVal| > maxAbs * ind * 2^{-53}) 00069 public: 00071 00072 00073 filteredFp (double val = 0.0) 00074 : fpVal(val), maxAbs(core_abs(val)), ind(0) {} 00076 filteredFp (double val, double m, int i) 00077 : fpVal(val), maxAbs(m), ind(i) {} 00078 00080 00082 filteredFp (const Real & value) : fpVal(0.0), maxAbs(0.0), ind(0) { 00083 if (value != CORE_REAL_ZERO) { 00084 ind = 1; 00085 fpVal = value.doubleValue(); 00086 if (value.MSB() <= -1075) 00087 maxAbs = 1; 00088 else 00089 maxAbs = core_abs(fpVal); // NaN are propagated correctly by core_abs. 00090 } 00091 } 00093 00095 00096 00097 double getValue() const { 00098 return fpVal; 00099 } 00101 bool isOK() const { 00102 return (fpFilterFlag && // To disable filter 00103 finite(fpVal) && // Test for infinite and NaNs 00104 (core_abs(fpVal) >= maxAbs*ind*CORE_EPS)); 00105 } 00107 00109 int sign() const { 00110 #ifdef CORE_DEBUG 00111 assert(isOK()); 00112 #endif 00113 if (fpVal == 0.0) 00114 return 0; 00115 else 00116 return fpVal > 0.0 ? 1: -1; 00117 } 00119 00122 extLong lMSB() const { 00123 return extLong(ilogb(core_abs(fpVal)-maxAbs*ind*CORE_EPS)); 00124 } 00126 extLong uMSB() const { 00127 return extLong(ilogb(core_abs(fpVal)+maxAbs*ind*CORE_EPS)); 00128 } 00130 00132 00133 00134 filteredFp operator -() const { 00135 return filteredFp(-fpVal, maxAbs, ind); 00136 } 00138 filteredFp operator+ (const filteredFp& x) const { 00139 return filteredFp(fpVal+x.fpVal, maxAbs+x.maxAbs, 1+core_max(ind, x.ind)); 00140 } 00142 filteredFp operator- (const filteredFp& x) const { 00143 return filteredFp(fpVal-x.fpVal, maxAbs+x.maxAbs, 1+core_max(ind, x.ind)); 00144 } 00146 filteredFp operator* (const filteredFp& x) const { 00147 return filteredFp(fpVal*x.fpVal, maxAbs*x.maxAbs+DBL_MIN, 1+ind+x.ind); 00148 } 00150 filteredFp operator/ (const filteredFp& x) const { 00151 if (x.fpVal == 0.0) 00152 core_error("possible zero divisor!", __FILE__, __LINE__, false); 00153 double xxx = core_abs(x.fpVal) / x.maxAbs - (x.ind+1)*CORE_EPS + DBL_MIN; 00154 if (xxx > 0) { 00155 double val = fpVal / x.fpVal; 00156 double maxVal = ( core_abs(val) + maxAbs / x.maxAbs) / xxx + DBL_MIN; 00157 return filteredFp(val, maxVal, 1 + core_max(ind, x.ind + 1)); 00158 } else 00159 return filteredFp(getDoubleInfty(), 0.0, 0); 00160 } 00162 filteredFp sqrt () const { 00163 if (fpVal < 0.0) 00164 core_error("possible negative sqrt!", __FILE__, __LINE__, false); 00165 if (fpVal > 0.0) { 00166 double val = std::sqrt(fpVal); 00167 return filteredFp(val, ( maxAbs / fpVal ) * val, 1 + ind); 00168 } else 00169 return filteredFp(0.0, std::sqrt(maxAbs) * POWTWO_26, 1 + ind); 00170 } 00171 00173 void dump (std::ostream&os) const { 00174 os << "Filter=[fpVal=" << fpVal << ",maxAbs=" << maxAbs << ",ind=" << ind << "]"; 00175 } 00176 00178 static double getDoubleInfty() { 00179 static double d = DBL_MAX; 00180 return 2*d; 00181 } 00183 }; //filteredFp class 00184 00185 inline std::ostream & operator<< (std::ostream & os, const filteredFp& fp) { 00186 fp.dump(os); 00187 return os; 00188 } 00189 00190 CORE_END_NAMESPACE 00191 #endif // _CORE_FILTER_H_ 00192