|
BWAPI
|
00001 // Copyright (c) 2006-2008 Max-Planck-Institute Saarbruecken (Germany). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License as 00006 // published by the Free Software Foundation; version 2.1 of the License. 00007 // See the file LICENSE.LGPL distributed with CGAL. 00008 // 00009 // Licensees holding a valid commercial license may use this file in 00010 // accordance with the commercial license agreement provided with the software. 00011 // 00012 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00013 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00014 // 00015 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Number_types/include/CGAL/CORE_BigFloat.h $ 00016 // $Id: CORE_BigFloat.h 49632 2009-05-26 21:08:11Z efif $ 00017 // 00018 // 00019 // Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de> 00020 //============================================================================ 00021 00022 #ifndef CGAL_CORE_BIGFLOAT_H 00023 #define CGAL_CORE_BIGFLOAT_H 00024 00025 #include <CGAL/basic.h> 00026 #include <CGAL/number_type_basic.h> 00027 #include <CGAL/CORE/BigFloat.h> 00028 #include <CGAL/CORE_coercion_traits.h> 00029 #include <CGAL/Interval_traits.h> 00030 #include <CGAL/Bigfloat_interval_traits.h> 00031 00032 CGAL_BEGIN_NAMESPACE 00033 00034 // ######### Interval_traits 00035 00036 template<> 00037 class Interval_traits<CORE::BigFloat> 00038 : public CGALi::Interval_traits_base<CORE::BigFloat>{ 00039 00040 public: 00041 00042 typedef Interval_traits<CORE::BigFloat> Self; 00043 typedef CORE::BigFloat Interval; 00044 typedef CORE::BigFloat Boundary; 00045 typedef CGAL::Tag_true Is_interval; 00046 00047 struct Lower :public std::unary_function<Interval,Boundary>{ 00048 Boundary operator() ( Interval x ) const { 00049 CORE::BigFloat result = ::CORE::BigFloat(x.m()-x.err(),0,x.exp()); 00050 CGAL_postcondition(result <= x); 00051 return result; 00052 } 00053 }; 00054 00055 struct Upper :public std::unary_function<Interval,Boundary>{ 00056 Boundary operator() ( Interval x ) const { 00057 CORE::BigFloat result = ::CORE::BigFloat(x.m()+x.err(),0,x.exp()); 00058 CGAL_postcondition(result >= x); 00059 return result; 00060 } 00061 }; 00062 00063 struct Width :public std::unary_function<Interval,Boundary>{ 00064 00065 Boundary operator() ( Interval x ) const { 00066 unsigned long err = 2*x.err(); 00067 return Boundary(CORE::BigInt(err),0,x.exp()); 00068 } 00069 }; 00070 00071 struct Median :public std::unary_function<Interval,Boundary>{ 00072 00073 Boundary operator() ( Interval x ) const { 00074 return Boundary(x.m(),0,x.exp()); 00075 } 00076 }; 00077 00078 struct Norm :public std::unary_function<Interval,Boundary>{ 00079 Boundary operator() ( Interval x ) const { 00080 BOOST_USING_STD_MAX(); 00081 return max BOOST_PREVENT_MACRO_SUBSTITUTION (Upper()(x).abs(),Lower()(x).abs()); 00082 } 00083 }; 00084 00085 struct Zero_in :public std::unary_function<Interval,bool>{ 00086 bool operator() ( Interval x ) const { 00087 return x.isZeroIn(); 00088 } 00089 }; 00090 00091 struct In :public std::binary_function<Boundary,Interval,bool>{ 00092 bool operator()( Boundary x, const Interval& a ) const { 00093 CGAL_precondition(CGAL::singleton(x)); 00094 return (Lower()(a) <= x && x <= Upper()(a)); 00095 } 00096 }; 00097 00098 struct Equal :public std::binary_function<Interval,Interval,bool>{ 00099 bool operator()( const Interval& a, const Interval& b ) const { 00100 return (Upper()(a) == Upper()(b) && Lower()(a) == Lower()(b)); 00101 } 00102 }; 00103 00104 struct Subset :public std::binary_function<Interval,Interval,bool>{ 00105 bool operator()( const Interval& a, const Interval& b ) const { 00106 return Lower()(b) <= Lower()(a) && Upper()(a) <= Upper()(b); 00107 } 00108 }; 00109 00110 struct Proper_subset :public std::binary_function<Interval,Interval,bool>{ 00111 bool operator()( const Interval& a, const Interval& b ) const { 00112 return Subset()(a,b) && (!Equal()(a,b)); 00113 } 00114 }; 00115 00116 struct Intersection :public std::binary_function<Interval,Interval,Interval>{ 00117 Interval operator()( const Interval& a, const Interval& b ) const { 00118 BOOST_USING_STD_MAX(); 00119 BOOST_USING_STD_MIN(); 00120 // std::cout <<"a= (" << a.m() << "+-" << a.err() << ")*2^" << a.exp() << std::endl; 00121 Boundary l(max BOOST_PREVENT_MACRO_SUBSTITUTION (Lower()(a),Lower()(b))); 00122 Boundary u(min BOOST_PREVENT_MACRO_SUBSTITUTION (Upper()(a),Upper()(b))); 00123 00124 if(u < l ) throw Exception_intersection_is_empty(); 00125 return Construct()(l,u); 00126 } 00127 }; 00128 00129 00130 struct Overlap :public std::binary_function<Interval,Interval,bool>{ 00131 bool operator() ( Interval x, Interval y ) const { 00132 Self::Zero_in Zero_in; 00133 bool result = Zero_in(x-y); 00134 return result; 00135 } 00136 }; 00137 00138 struct Hull :public std::binary_function<Interval,Interval,Interval>{ 00139 00140 /* for debugging 00141 void print_bf(CORE::BigFloat bf, std::string s) const { 00142 00143 std::cout << s << ".m()=" << bf.m() << "," 00144 << s << ".err()=" << bf.err() << "," 00145 << s << ".exp()=" << bf.exp() << "," 00146 << "td=" << bf << std::endl; 00147 } 00148 */ 00149 00150 Interval operator() ( Interval x, Interval y ) const { 00151 BOOST_USING_STD_MAX(); 00152 BOOST_USING_STD_MIN(); 00153 #if 0 00154 // this is not possible since CORE::centerize has a bug. 00155 Interval result = CORE::centerize(x,y); 00156 #else 00157 00158 //print_bf(x,"x"); 00159 //print_bf(y,"y"); 00160 00161 CORE::BigFloat result; 00162 00163 // Unfortunately, CORE::centerize(x,y) has bugs. 00164 if ((x.m() == y.m()) && (x.err() == y.err()) && (x.exp() == y.exp())) { 00165 return x; 00166 } 00167 00168 CORE::BigFloat lower = min BOOST_PREVENT_MACRO_SUBSTITUTION (CGAL::lower(x), CGAL::lower(y)); 00169 CORE::BigFloat upper = max BOOST_PREVENT_MACRO_SUBSTITUTION (CGAL::upper(x), CGAL::upper(y)); 00170 00171 CORE::BigFloat mid = (lower + upper)/2; 00172 00173 //print_bf(lower,"lower"); 00174 //print_bf(upper,"upper"); 00175 //print_bf(mid,"mid"); 00176 00177 // Now we have to compute the error. The problem is that .err() is just a long 00178 CORE::BigFloat err = (upper - lower)/CORE::BigFloat(2); 00179 00180 //print_bf(err,"err"); 00181 00182 //std::cout << "lower " << lower << std::endl; 00183 //std::cout << "upper " << upper << std::endl; 00184 //std::cout << "mid " << mid << std::endl; 00185 //std::cout << "err I " << err << std::endl; 00186 00187 // shift such that err.m()+err.err() fits into long 00188 int digits_long = std::numeric_limits<long>::digits; 00189 if(::CORE::bitLength(err.m()+err.err()) >= digits_long){ 00190 long shift = ::CORE::bitLength(err.m()) - digits_long + 1 ; 00191 //std::cout << "shift " << shift<< std::endl; 00192 long new_err = ((err.m()+err.err()) >> shift).longValue()+1; 00193 err = CORE::BigFloat(0,new_err,0) * CORE::BigFloat::exp2(err.exp()*14+shift); 00194 }else{ 00195 err = CORE::BigFloat(0,err.m().longValue()+err.err(),err.exp()); 00196 } 00197 //print_bf(err,"new_err"); 00198 00199 // TODO: This is a workaround for a bug in operator+ 00200 // of CORE::Bigfloat. If the exponent difference is too big, 00201 // this might cause problems, since the error is a long 00202 if(mid.exp() > err.exp()) { 00203 long mid_err = mid.err(); 00204 CORE::BigInt mid_m = mid.m(); 00205 mid_err = mid_err << (mid.exp()-err.exp())*14; 00206 mid_m = mid_m << (mid.exp()-err.exp())*14; 00207 mid = CORE::BigFloat(mid_m,mid_err,err.exp()); 00208 //print_bf(mid,"corr_mid"); 00209 } 00210 00211 //print_bf(result,"result"); 00212 00213 result = mid + err; 00214 00215 #endif 00216 00217 CGAL_postcondition( 00218 CGAL::lower(result) 00219 <= min BOOST_PREVENT_MACRO_SUBSTITUTION (CGAL::lower(x), CGAL::lower(y))); 00220 CGAL_postcondition( 00221 CGAL::upper(result) 00222 >= max BOOST_PREVENT_MACRO_SUBSTITUTION (CGAL::upper(x), CGAL::upper(y))); 00223 00224 00225 00226 return result ; 00227 } 00228 }; 00229 00230 struct Singleton :public std::unary_function<Interval,bool> { 00231 bool operator() ( Interval x ) const { 00232 return (x.err() == 0); 00233 } 00234 }; 00235 00236 struct Construct :public std::binary_function<Boundary,Boundary,Interval>{ 00237 Interval operator()( const Boundary& l,const Boundary& r) const { 00238 CGAL_precondition( l < r ); 00239 return Hull()(l,r); 00240 } 00241 }; 00242 }; 00243 00244 00245 // ########### Bigfloat_interval_traits 00246 00247 00248 template<typename BFI> long get_significant_bits(BFI bfi); 00249 00250 CORE::BigFloat 00251 inline 00252 round(const CORE::BigFloat& x, long rel_prec = CORE::defRelPrec.toLong() ){ 00253 CGAL_postcondition(rel_prec >= 0); 00254 00255 // since there is not rel prec defined if Zero_in(x) 00256 if (x.isZeroIn()) return x; 00257 if (CGAL::get_significant_bits(x) <= rel_prec) return x; 00258 00259 // if 1 00260 // CORE::BigFloat xr; 00261 // xr.approx(x,rel_prec,1024); 00262 // typedef CORE::BigFloat BF; 00263 // else 00264 typedef CORE::BigFloat BF; 00265 typedef CORE::BigFloat BFI; 00266 typedef CORE::BigInt Integer; 00267 BF xr; 00268 00269 CORE::BigInt m = x.m(); 00270 long err = x.err(); 00271 long exp = x.exp(); 00272 00273 long shift = ::CORE::bitLength(m) - rel_prec - 1; 00274 if( shift > 0 ){ Integer new_m = m >> shift ; 00275 if(err == 0){ xr = BF(new_m,1,0)*BF::exp2(exp*14+shift); 00276 }else{ xr = BF(new_m,2,0)*BF::exp2(exp*14+shift); 00277 } 00278 }else{ // noting to do 00279 xr = x; 00280 } 00281 // endif 00282 00283 CGAL_postcondition(CGAL::get_significant_bits(xr) - rel_prec >= 0); 00284 CGAL_postcondition(CGAL::get_significant_bits(xr) - rel_prec <= 32); 00285 CGAL_postcondition(BF(xr.m()-xr.err(),0,xr.exp()) <= BF(x.m()-x.err(),0,x.exp())); 00286 CGAL_postcondition(BF(xr.m()+xr.err(),0,xr.exp()) >= BF(x.m()+x.err(),0,x.exp())); 00287 return xr; 00288 } 00289 00290 template<> class Bigfloat_interval_traits<CORE::BigFloat> 00291 :public Interval_traits<CORE::BigFloat> 00292 { 00293 public: 00294 typedef CORE::BigFloat NT; 00295 typedef CORE::BigFloat BF; 00296 00297 typedef Bigfloat_interval_traits<NT> Self; 00298 00299 // How about retuning 00300 struct Get_significant_bits { 00301 // type for the \c AdaptableUnaryFunction concept. 00302 typedef NT argument_type; 00303 // type for the \c AdaptableUnaryFunction concept. 00304 typedef long result_type; 00305 00306 long operator()( NT x) const { 00307 if(x.err() == 0 ) { 00308 return ::CORE::bitLength(x.m()); 00309 } 00310 else { 00311 return ::CORE::bitLength(x.m()) - ::CORE::bitLength(x.err()); 00312 } 00313 } 00314 }; 00315 00316 struct Set_precision { 00317 // type for the \c AdaptableUnaryFunction concept. 00318 typedef long argument_type; 00319 // type for the \c AdaptableUnaryFunction concept. 00320 typedef long result_type; 00321 00322 long operator() ( long prec ) const { 00323 long result = ::CORE::defRelPrec.toLong(); 00324 ::CORE::defRelPrec = prec; 00325 ::CORE::defBFdivRelPrec = prec; 00326 return result; 00327 } 00328 }; 00329 00330 struct Get_precision { 00331 // type for the \c AdaptableGenerator concept. 00332 typedef long result_type; 00333 00334 long operator() () const { 00335 return ::CORE::defRelPrec.toLong(); 00336 } 00337 }; 00338 }; 00339 00340 00341 00342 00343 // 00344 // Algebraic structure traits 00345 // 00346 template <> class Algebraic_structure_traits< CORE::BigFloat > 00347 : public Algebraic_structure_traits_base< CORE::BigFloat, 00348 Field_with_kth_root_tag > { 00349 public: 00350 typedef Tag_false Is_exact; 00351 typedef Tag_true Is_numerical_sensitive; 00352 00353 class Sqrt 00354 : public std::unary_function< Type, Type > { 00355 public: 00356 Type operator()( const Type& x ) const { 00357 // What I want is a sqrt computed with ::CORE::defRelPrec bits. 00358 // And not ::CORE::defBFsqrtAbsPrec as CORE does. 00359 00360 CGAL_precondition(::CORE::defRelPrec.toLong() > 0); 00361 CGAL_precondition(x > 0); 00362 00363 Type a = CGAL::round(x, ::CORE::defRelPrec.toLong()*2); 00364 CGAL_postcondition(a > 0); 00365 00366 Type tmp1 = 00367 CORE::BigFloat(a.m(),0,0).sqrt(::CORE::defRelPrec.toLong()); 00368 Type err = 00369 Type(0,long(std::sqrt(double(a.err()))),0) 00370 * CORE::BigFloat::exp2(a.exp()*7); 00371 Type result = tmp1*CORE::BigFloat::exp2(a.exp()*7) + err; 00372 00373 CGAL_postcondition(result >= 0); 00374 CGAL_postcondition(CGAL::lower(result*result) <= CGAL::lower(x)); 00375 CGAL_postcondition(CGAL::upper(result*result) >= CGAL::upper(x)); 00376 00377 return result; 00378 } 00379 }; 00380 00381 class Kth_root 00382 : public std::binary_function<int, Type, Type> { 00383 public: 00384 Type operator()( int k, 00385 const Type& x) const { 00386 CGAL_precondition_msg( k > 0, "'k' must be positive for k-th roots"); 00387 // CORE::radical isn't implemented for negative values of x, so we 00388 // have to handle this case separately 00389 if( x < 0 && k%2 != 0) { 00390 return Type(-CORE::radical( -x, k ) ); 00391 } 00392 00393 return Type( CORE::radical( x, k ) ); 00394 } 00395 }; 00396 }; 00397 00398 // 00399 // Real embeddable traits 00400 // 00401 template <> class Real_embeddable_traits< CORE::BigFloat > 00402 : public INTERN_RET::Real_embeddable_traits_base< CORE::BigFloat , CGAL::Tag_true > { 00403 public: 00404 class Abs 00405 : public std::unary_function< Type, Type > { 00406 public: 00407 Type operator()( const Type& x ) const { 00408 Type result; 00409 00410 if(x.isZeroIn()){ 00411 CORE::BigInt m; 00412 if(x.m() < 0 ){ 00413 m = -(x.m()-x.err()); 00414 }else{ 00415 m = x.m()+x.err(); 00416 } 00417 if(m % 2 == 1) m += 1; 00418 00419 Type upper(m,0,x.exp()); 00420 result = CORE::centerize(CORE::BigFloat(0),upper); 00421 00422 CGAL_postcondition(result.m()-result.err() <= 0); 00423 if(result.m()-result.err() != 0){ 00424 result = this->operator()(result); 00425 } 00426 CGAL_postcondition(result.m()-result.err() == 0); 00427 }else{ 00428 result = CORE::abs(x); 00429 } 00430 CGAL_postcondition(result.m()-result.err() >= 0); 00431 CGAL_postcondition(Type(result.m()+result.err(),0,result.exp()) 00432 >= Type(x.m()+x.err(),0,x.exp())); 00433 return result; 00434 } 00435 }; 00436 00437 class Sgn 00438 : public std::unary_function< Type, ::CGAL::Sign > { 00439 public: 00440 ::CGAL::Sign operator()( const Type& x ) const { 00441 ::CGAL::Sign result = sign( x.sign()); 00442 return result; 00443 } 00444 }; 00445 00446 class Compare 00447 : public std::binary_function< Type, Type, 00448 Comparison_result > { 00449 public: 00450 Comparison_result operator()( const Type& x, 00451 const Type& y ) const { 00452 return (Comparison_result) sign( (x-y).sign()); 00453 } 00454 CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT( Type, 00455 Comparison_result ) 00456 }; 00457 00458 class To_double 00459 : public std::unary_function< Type, double > { 00460 public: 00461 double operator()( const Type& x ) const { 00462 // this call is required to get reasonable values for the double 00463 // approximation 00464 return x.doubleValue(); 00465 } 00466 }; 00467 00468 class To_interval 00469 : public std::unary_function< Type, std::pair< double, double > > { 00470 public: 00471 std::pair<double, double> operator()( const Type& x ) const { 00472 00473 double lb,ub; 00474 00475 Type x_lower = CGAL::lower(CGAL::round(CGAL::lower(x),52)); 00476 Type x_upper = CGAL::upper(CGAL::round(CGAL::upper(x),52)); 00477 00478 // since matissa has 52 bits only, conversion to double is exact 00479 lb = x_lower.doubleValue(); 00480 CGAL_postcondition(lb == x_lower); 00481 ub = x_upper.doubleValue(); 00482 CGAL_postcondition(ub == x_upper); 00483 00484 std::pair<double, double> result(lb,ub); 00485 CGAL_postcondition( result.first <= CORE::Expr(CGAL::lower(x))); 00486 CGAL_postcondition( result.second >= CORE::Expr(CGAL::upper(x))); 00487 return result; 00488 } 00489 }; 00490 }; 00491 00492 CGAL_END_NAMESPACE 00493 00494 //since types are included by CORE_coercion_traits.h: 00495 #include <CGAL/CORE_Expr.h> 00496 #include <CGAL/CORE_BigInt.h> 00497 #include <CGAL/CORE_BigRat.h> 00498 #include <CGAL/CORE_BigFloat.h> 00499 00500 #endif // CGAL_CORE_BIGFLOAT_H
1.7.6.1