BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/CORE_BigFloat.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines