BWAPI
|
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