BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Modular_arithmetic/Residue_type.h
Go to the documentation of this file.
00001 // Copyright (c) 2007  INRIA Sophia-Antipolis (France), Max-Planck-Institute
00002 // Saarbruecken (Germany).
00003 // All rights reserved.
00004 //
00005 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public License as
00007 // published by the Free Software Foundation; version 2.1 of the License.
00008 // See the file LICENSE.LGPL distributed with CGAL.
00009 //
00010 // Licensees holding a valid commercial license may use this file in
00011 // accordance with the commercial license agreement provided with the software.
00012 //
00013 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00014 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00015 //
00016 // $URL:$
00017 // $Id:$
00018 //
00019 // Author(s)     : Sylvain Pion, Michael Hemmer
00020 
00021 #ifndef CGAL_RESIDUE_TYPE_H
00022 #define CGAL_RESIDUE_TYPE_H
00023 
00024 #include <CGAL/basic.h>
00025 
00026 #include <cfloat>
00027 #include <boost/operators.hpp>
00028 
00029 #ifdef CGAL_HAS_THREADS
00030 #  include <boost/thread/tss.hpp>
00031 #endif
00032 
00033 CGAL_BEGIN_NAMESPACE
00034 
00035 class Residue;
00036     
00037 Residue operator + (const Residue&);
00038 Residue operator - (const Residue&);
00039 
00040 std::ostream& operator << (std::ostream& os, const Residue& p);
00041 std::istream& operator >> (std::istream& is, Residue& p);
00042 
00054 class Residue:
00055     boost::ordered_field_operators1< Residue,
00056     boost::ordered_field_operators2< Residue, int > >{
00057     
00058 public:
00059     typedef Residue Self;
00060     typedef Residue NT;
00061 
00062 private:
00063     static const double  CST_CUT; 
00064 
00065 #ifdef CGAL_HAS_THREADS
00066   static boost::thread_specific_ptr<int>    prime_int_;
00067   static boost::thread_specific_ptr<double> prime_;
00068   static boost::thread_specific_ptr<double> prime_inv_;
00069   
00070   static void init_class_for_thread(){
00071     CGAL_precondition(prime_int_.get() == NULL); 
00072     CGAL_precondition(prime_.get()     == NULL); 
00073     CGAL_precondition(prime_inv_.get() == NULL); 
00074     prime_int_.reset(new int(67111067));
00075     prime_.reset(new double(67111067.0));
00076     prime_inv_.reset(new double(1.0/67111067.0));
00077   }
00078   
00079   static inline int get_prime_int(){
00080     if (prime_int_.get() == NULL)
00081       init_class_for_thread();
00082     return *prime_int_.get();
00083   }
00084   
00085   static inline double get_prime(){
00086     if (prime_.get() == NULL)
00087       init_class_for_thread();
00088     return *prime_.get();
00089   }
00090   
00091   static inline double get_prime_inv(){
00092     if (prime_inv_.get() == NULL)
00093       init_class_for_thread();
00094     return *prime_inv_.get();
00095   }
00096 #else
00097   static int prime_int;
00098   static double prime;
00099   static double prime_inv;
00100   static int get_prime_int(){ return prime_int;}
00101   static double get_prime()    { return prime;}
00102   static double get_prime_inv(){ return prime_inv;}  
00103 #endif
00104 
00105     /* Quick integer rounding, valid if a<2^51. for double */ 
00106     static inline 
00107     double RES_round (double a){
00108       // call CGAL::Protect_FPU_rounding<true> pfr(CGAL_FE_TONEAREST)
00109       // before using modular arithmetic 
00110       CGAL_assertion(FPU_get_cw() == CGAL_FE_TONEAREST);
00111       return ( (a + CST_CUT)  - CST_CUT);      
00112     }
00113 
00114     /* Big modular reduction (e.g. after multiplication) */
00115     static inline 
00116     double RES_reduce (double a){
00117       double result = a - get_prime() * RES_round(a * get_prime_inv());
00118       CGAL_postcondition(2*result <  get_prime());
00119       CGAL_postcondition(2*result > -get_prime());
00120       return result;
00121     }
00122 
00123     /* Little modular reduction (e.g. after a simple addition). */
00124     static inline 
00125     double RES_soft_reduce (double a){
00126       double p = get_prime();
00127         double b = 2*a;
00128         return (b>p) ? a-p :
00129             ((b<-p) ? a+p : a);
00130     }
00131 
00132     
00133     /* -a */
00134     static inline 
00135     double RES_negate(double a){
00136         return RES_soft_reduce(-a);
00137     }
00138 
00139 
00140     /* a*b */
00141     static inline 
00142     double RES_mul (double a, double b){
00143         double c = a*b;
00144         return RES_reduce(c);
00145     }
00146 
00147 
00148     /* a+b */
00149     static inline 
00150     double RES_add (double a, double b){
00151         double c = a+b;
00152         return RES_soft_reduce(c);
00153     }
00154 
00155     
00156     /* a^-1, using Bezout (extended Euclidian algorithm). */
00157     static inline 
00158     double RES_inv (double ri1){
00159         double bi = 0.0;
00160         double bi1 = 1.0;
00161         double ri = get_prime();
00162         double p, tmp, tmp2;
00163     
00164         Real_embeddable_traits<double>::Abs double_abs;
00165         while (double_abs(ri1) != 1.0)
00166         {
00167             p = RES_round(ri/ri1);
00168             tmp = bi - p * bi1;
00169             tmp2 = ri - p * ri1;
00170             bi = bi1;
00171             ri = ri1;
00172             bi1 = tmp;
00173             ri1 = tmp2;
00174         };
00175 
00176         return ri1 * RES_soft_reduce(bi1);      /* Quicker !!!! */
00177     }
00178     
00179     /* a/b */
00180     static inline 
00181     double RES_div (double a, double b){
00182         return RES_mul(a, RES_inv(b));
00183     }    
00184 
00185 public:
00193     static int 
00194     set_current_prime(int p){   
00195       int old_prime = get_prime_int();  
00196 #ifdef CGAL_HAS_THREADS
00197       *prime_int_.get() = p;
00198       *prime_.get() = double(p);
00199       *prime_inv_.get() = 1.0/double(p);
00200 #else
00201       prime_int = p;
00202       prime = double(p);
00203       prime_inv = 1.0 / prime;
00204 #endif
00205       return old_prime; 
00206     }
00207  
00209     static int get_current_prime(){
00210       return get_prime_int();
00211     }
00212   
00213   int  get_value() const{
00214     CGAL_precondition(2*x_ <  get_prime());
00215     CGAL_precondition(2*x_ > -get_prime());
00216     return int(x_);
00217   }
00218     
00219 private:
00220     double x_;
00221 
00222 public: 
00223 
00225     Residue(int n = 0){
00226         x_= RES_reduce(n);
00227     }
00228 
00230     Residue(long n){
00231         x_= RES_reduce(n);
00232     }
00233    
00235     const double& x() const { return x_; }
00237     double&       x()       { return x_; }                     
00238 
00239     Self& operator += (const Self& p2) { 
00240         x() = RES_add(x(),p2.x()); 
00241         return (*this); 
00242     }
00243     Self& operator -= (const Self& p2){ 
00244         x() = RES_add(x(),RES_negate(p2.x())); 
00245         return (*this); 
00246     }
00247     Self& operator *= (const Self& p2){ 
00248         x() = RES_mul(x(),p2.x()); 
00249         return (*this); 
00250     }
00251     Self& operator /= (const Self& p2) { 
00252         x() = RES_div(x(),p2.x()); 
00253         return (*this); 
00254     }
00255     // 
00256     Self& operator += (int p2) { 
00257         x() = RES_add(x(),Residue(p2).x()); 
00258         return (*this); 
00259     }
00260     Self& operator -= (int p2){ 
00261         x() = RES_add(x(),Residue(-p2).x()); 
00262         return (*this); 
00263     }
00264 
00265     Self& operator *= (int p2){ 
00266         x() = RES_mul(x(),Residue(p2).x()); 
00267         return (*this); 
00268     }
00269 
00270     Self& operator /= (int p2) { 
00271         x() = RES_div(x(),Residue(p2).x()); 
00272         return (*this); 
00273     }
00274   
00275     friend Self operator + (const Self&);
00276     friend Self operator - (const Self&);                
00277 };
00278 
00279 inline Residue operator + (const Residue& p1)
00280 { return p1; }
00281 
00282 inline Residue operator - (const Residue& p1){ 
00283     typedef Residue RES;
00284     Residue r; 
00285     r.x() = RES::RES_negate(p1.x());
00286     return r; 
00287 }
00288 
00289 inline bool operator == (const Residue& p1, const Residue& p2)
00290 { return ( p1.x()==p2.x() ); }   
00291 inline bool operator == (const Residue& p1, int p2)
00292 { return ( p1 == Residue(p2) ); }   
00293 
00294 
00295 inline bool operator < (const Residue& p1, const Residue& p2)
00296 { return ( p1.x() < p2.x() ); }   
00297 inline bool operator < (const Residue& p1, int p2)
00298 { return ( p1.x() < Residue(p2).x() ); }   
00299 
00300 
00301 // I/O 
00302 inline std::ostream& operator << (std::ostream& os, const Residue& p) {   
00303     typedef Residue RES;
00304     os <<"("<< int(p.x())<<"%"<<RES::get_current_prime()<<")";
00305     return os;
00306 }
00307 
00308 inline std::istream& operator >> (std::istream& is, Residue& p) {
00309     typedef Residue RES;
00310     char ch;
00311     int prime;
00312 
00313     is >> p.x();
00314     is >> ch;    // read the %
00315     is >> prime; // read the prime
00316     CGAL_precondition(prime==RES::get_current_prime());
00317     return is;
00318 }
00319 
00320 CGAL_END_NAMESPACE
00321 
00322 #endif // CGAL_RESIDUE_TYPE_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines