BWAPI
|
00001 // Copyright (c) 1999,2003,2004 Utrecht University (The Netherlands), 00002 // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany), 00003 // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg 00004 // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria), 00005 // and Tel-Aviv University (Israel). All rights reserved. 00006 // 00007 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or 00008 // modify it under the terms of the GNU Lesser General Public License as 00009 // published by the Free Software Foundation; version 2.1 of the License. 00010 // See the file LICENSE.LGPL distributed with CGAL. 00011 // 00012 // Licensees holding a valid commercial license may use this file in 00013 // accordance with the commercial license agreement provided with the software. 00014 // 00015 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00016 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00017 // 00018 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Number_types/include/CGAL/GMP/Gmpz_type.h $ 00019 // $Id: Gmpz_type.h 49008 2009-04-29 13:57:45Z hemmer $ 00020 // 00021 // 00022 // Author(s) : Andreas Fabri, Stefan Schirra, Sylvain Pion 00023 00024 00025 #ifndef CGAL_GMPZ_TYPE_H 00026 #define CGAL_GMPZ_TYPE_H 00027 00028 #include <CGAL/basic.h> 00029 #include <gmp.h> 00030 #include <mpfr.h> 00031 00032 #include <boost/operators.hpp> 00033 #include <CGAL/Handle_for.h> 00034 00035 #include <string> 00036 #include <locale> 00037 00038 CGAL_BEGIN_NAMESPACE 00039 00040 // TODO : benchmark without ref-counting, and maybe give the possibility 00041 // to select ref-counting or not, then... => template class. 00042 00043 // Wrapper around mpz_t to get the destructor call mpz_clear. 00044 struct Gmpz_rep 00045 { 00046 // FIXME : bug if ~() is called before an mpz_init*() is called. 00047 // not a problem in practice, but not nice. 00048 // maybe the mpz_init_set* functions should move back to Gmpz_rep. 00049 // But then we should use the Storage_traits::construct/get... 00050 00051 mpz_t mpZ; 00052 00053 Gmpz_rep() {} 00054 ~Gmpz_rep() { mpz_clear(mpZ); } 00055 00056 private: 00057 // Make sure it does not get accidentally copied. 00058 Gmpz_rep(const Gmpz_rep &); 00059 Gmpz_rep & operator= (const Gmpz_rep &); 00060 }; 00061 00062 00063 class Gmpz 00064 : Handle_for<Gmpz_rep>, 00065 boost::ordered_euclidian_ring_operators1< Gmpz 00066 , boost::ordered_euclidian_ring_operators2< Gmpz, int 00067 > > 00068 { 00069 typedef Handle_for<Gmpz_rep> Base; 00070 public: 00071 typedef Tag_true Has_gcd; 00072 typedef Tag_true Has_division; 00073 typedef Tag_true Has_sqrt; 00074 00075 typedef Tag_true Has_exact_ring_operations; 00076 typedef Tag_true Has_exact_division; 00077 typedef Tag_false Has_exact_sqrt; 00078 00079 Gmpz() 00080 { mpz_init(mpz()); } 00081 00082 Gmpz(const mpz_t z) 00083 { mpz_init_set(mpz(), z); } 00084 00085 Gmpz(int i) 00086 { mpz_init_set_si(mpz(), i); } 00087 00088 Gmpz(long l) 00089 { mpz_init_set_si(mpz(), l); } 00090 00091 Gmpz(unsigned long l) 00092 { mpz_init_set_ui(mpz(), l); } 00093 00094 Gmpz(double d) 00095 { 00096 CGAL_warning_msg(is_integer(d), "Gmpz constructed from non-integer double value"); 00097 CGAL_assertion(is_finite(d)); 00098 mpz_init_set_d(mpz(), d); 00099 } 00100 00101 Gmpz(const std::string& str, int base = 10) 00102 { mpz_init_set_str(mpz(), str.c_str(), base); } 00103 00104 Gmpz operator+() const; 00105 Gmpz operator-() const; 00106 00107 Gmpz& operator+=(const Gmpz &z); 00108 Gmpz& operator+=(int i); 00109 00110 Gmpz& operator-=(const Gmpz &z); 00111 Gmpz& operator-=(int i); 00112 00113 Gmpz& operator*=(const Gmpz &z); 00114 Gmpz& operator*=(int i); 00115 00116 Gmpz& operator%=(const Gmpz &z); 00117 00118 Gmpz& operator/=(const Gmpz &z); 00119 Gmpz& operator/=(int i); 00120 00121 size_t approximate_decimal_length() const; 00122 00123 double to_double() const; 00124 Sign sign() const; 00125 00126 const mpz_t & mpz() const { return Ptr()->mpZ; } 00127 mpz_t & mpz() { return ptr()->mpZ; } 00128 00129 #ifdef CGAL_ROOT_OF_2_ENABLE_HISTOGRAM_OF_NUMBER_OF_DIGIT_ON_THE_COMPLEX_CONSTRUCTOR 00130 int tam() const { return 0; } // put here a code 00131 // measuring the number of digits 00132 // of the Gmpz 00133 #endif 00134 00135 // Gives the memory size in bytes. (not documented yet) 00136 std::size_t size() const 00137 { 00138 return mpz_size(mpz()) / (mp_bits_per_limb/8); 00139 } 00140 }; 00141 00142 00143 inline 00144 bool 00145 operator<(const Gmpz &a, const Gmpz &b) 00146 { return mpz_cmp(a.mpz(), b.mpz()) < 0; } 00147 00148 inline 00149 bool 00150 operator==(const Gmpz &a, const Gmpz &b) 00151 { return mpz_cmp(a.mpz(), b.mpz()) == 0; } 00152 00153 00154 // mixed operators. 00155 inline 00156 bool 00157 operator<(const Gmpz &a, int b) 00158 { return mpz_cmp_si(a.mpz(), b) < 0; } 00159 00160 inline 00161 bool 00162 operator==(const Gmpz &a, int b) 00163 { return mpz_cmp_si(a.mpz(), b) == 0; } 00164 00165 inline 00166 bool 00167 operator>(const Gmpz &a, int b) 00168 { return mpz_cmp_si(a.mpz(), b) > 0; } 00169 00170 00171 inline 00172 Gmpz 00173 Gmpz::operator+() const { 00174 return Gmpz( mpz() ); 00175 } 00176 00177 inline 00178 Gmpz 00179 Gmpz::operator-() const 00180 { 00181 Gmpz Res; 00182 mpz_neg(Res.mpz(), mpz()); 00183 return Res; 00184 } 00185 00186 00187 inline 00188 Gmpz& 00189 Gmpz::operator+=(const Gmpz &z) 00190 { 00191 Gmpz Res; 00192 mpz_add(Res.mpz(), mpz(), z.mpz()); 00193 swap(Res); 00194 return *this; 00195 } 00196 00197 inline 00198 Gmpz& 00199 Gmpz::operator+=(int i) 00200 { 00201 Gmpz Res; 00202 if (i >= 0) 00203 mpz_add_ui(Res.mpz(), mpz(), i); 00204 else 00205 mpz_sub_ui(Res.mpz(), mpz(), -i); 00206 swap(Res); 00207 return *this; 00208 } 00209 00210 inline 00211 Gmpz& 00212 Gmpz::operator-=(const Gmpz &z) 00213 { 00214 Gmpz Res; 00215 mpz_sub(Res.mpz(), mpz(), z.mpz()); 00216 swap(Res); 00217 return *this; 00218 } 00219 00220 inline 00221 Gmpz& 00222 Gmpz::operator-=(int i) 00223 { 00224 Gmpz Res; 00225 if (i >= 0) 00226 mpz_sub_ui(Res.mpz(), mpz(), i); 00227 else 00228 mpz_add_ui(Res.mpz(), mpz(), -i); 00229 swap(Res); 00230 return *this; 00231 } 00232 00233 inline 00234 Gmpz& 00235 Gmpz::operator*=(const Gmpz &z) 00236 { 00237 Gmpz Res; 00238 mpz_mul(Res.mpz(), mpz(), z.mpz()); 00239 swap(Res); 00240 return *this; 00241 } 00242 00243 inline 00244 Gmpz& 00245 Gmpz::operator*=(int i) 00246 { 00247 Gmpz Res; 00248 mpz_mul_si(Res.mpz(), mpz(), i); 00249 swap(Res); 00250 return *this; 00251 } 00252 00253 inline 00254 Gmpz& 00255 Gmpz::operator/=(const Gmpz &z) 00256 { 00257 CGAL_precondition(z != 0); 00258 Gmpz Res; 00259 mpz_tdiv_q(Res.mpz(), mpz(), z.mpz()); 00260 swap(Res); 00261 return *this; 00262 } 00263 00264 inline 00265 Gmpz& 00266 Gmpz::operator/=(int b) 00267 { 00268 if (b>0) 00269 { 00270 Gmpz Res; 00271 mpz_tdiv_q_ui(Res.mpz(), mpz(), b); 00272 swap(Res); 00273 return *this; 00274 } 00275 return *this /= Gmpz(b); 00276 } 00277 00278 inline 00279 Gmpz& 00280 Gmpz::operator%=(const Gmpz &z) 00281 { 00282 Gmpz Res; 00283 mpz_tdiv_r(Res.mpz(), mpz(), z.mpz()); 00284 swap(Res); 00285 return *this; 00286 } 00287 00288 00289 inline 00290 double 00291 Gmpz::to_double() const 00292 { return mpz_get_d(mpz()); } 00293 00294 inline 00295 Sign 00296 Gmpz::sign() const 00297 { return static_cast<Sign>(mpz_sgn(mpz())); } 00298 00299 inline 00300 size_t 00301 Gmpz::approximate_decimal_length() const 00302 { return mpz_sizeinbase(mpz(),10); } 00303 00304 inline 00305 std::ostream& 00306 operator<<(std::ostream& os, const Gmpz &z) 00307 { 00308 char *str = new char [mpz_sizeinbase(z.mpz(),10) + 2]; 00309 str = mpz_get_str(str, 10, z.mpz()); 00310 os << str ; 00311 delete[] str; 00312 return os; 00313 } 00314 00315 inline 00316 void gmpz_eat_white_space(std::istream &is) 00317 { 00318 std::istream::int_type c; 00319 do { 00320 c= is.peek(); 00321 if (c== std::istream::traits_type::eof()) 00322 return; 00323 else { 00324 std::istream::char_type cc= c; 00325 if ( std::isspace(cc, std::locale::classic()) ) { 00326 is.get(); 00327 // since peek succeeded, this should too 00328 CGAL_assertion(!is.fail()); 00329 } else { 00330 return; 00331 } 00332 } 00333 } while (true); 00334 } 00335 00336 00337 inline 00338 std::istream & 00339 gmpz_new_read(std::istream &is, Gmpz &z) 00340 { 00341 bool negative = false; 00342 const std::istream::char_type zero = '0'; 00343 std::istream::int_type c; 00344 Gmpz r; 00345 std::ios::fmtflags old_flags = is.flags(); 00346 00347 is.unsetf(std::ios::skipws); 00348 gmpz_eat_white_space(is); 00349 00350 c=is.peek(); 00351 if (c=='-' || c=='+'){ 00352 is.get(); 00353 CGAL_assertion(!is.fail()); 00354 negative=(c=='-'); 00355 gmpz_eat_white_space(is); 00356 c=is.peek(); 00357 } 00358 00359 std::istream::char_type cc= c; 00360 00361 if (c== std::istream::traits_type::eof() || 00362 !std::isdigit(cc, std::locale::classic() ) ){ 00363 is.setstate(std::ios_base::failbit); 00364 } else { 00365 CGAL_assertion(cc==c); 00366 r= cc-zero; 00367 is.get(); 00368 CGAL_assertion(!is.fail()); 00369 while (true) { 00370 c=is.peek(); 00371 if (c== std::istream::traits_type::eof()) { 00372 break; 00373 } 00374 cc=c; 00375 if ( !std::isdigit(cc, std::locale::classic() )) { 00376 break; 00377 } 00378 is.get(); 00379 CGAL_assertion(!is.fail()); 00380 CGAL_assertion(cc==c); 00381 r= r*10+(cc-zero); 00382 } 00383 } 00384 00385 is.flags(old_flags); 00386 if (!is.fail()) { 00387 if (negative) { 00388 z=-r; 00389 } else { 00390 z=r; 00391 } 00392 } 00393 return is; 00394 } 00395 00396 /*inline 00397 std::istream& 00398 read_gmpz(std::istream& is, Gmpz &z) { 00399 bool negative = false; 00400 bool good = false; 00401 const int null = '0'; 00402 char c; 00403 Gmpz tmp; 00404 std::ios::fmtflags old_flags = is.flags(); 00405 00406 is.unsetf(std::ios::skipws); 00407 while (is.get(c) && std::isspace(c, std::locale::classic() )) 00408 {} 00409 00410 if (c == '-') 00411 { 00412 negative = true; 00413 while (is.get(c) && std::isspace(c, std::locale::classic() )) 00414 {} 00415 } 00416 if (std::isdigit(c, std::locale::classic() )) 00417 { 00418 good = true; 00419 tmp = c - null; 00420 while (is.get(c) && std::isdigit(c, std::locale::classic() )) 00421 { 00422 tmp = 10*tmp + (c-null); 00423 } 00424 } 00425 if (is) 00426 is.putback(c); 00427 if (sign(tmp) != ZERO && negative) 00428 tmp = -tmp; 00429 if (good){ 00430 z = tmp; 00431 } 00432 else 00433 is.clear(is.rdstate() | std::ios::failbit); 00434 00435 is.flags(old_flags); 00436 return is; 00437 }*/ 00438 00439 inline 00440 std::istream& 00441 operator>>(std::istream& is, Gmpz &z) 00442 { 00443 return gmpz_new_read(is, z); 00444 } 00445 00446 template <> 00447 struct Split_double<Gmpz> 00448 { 00449 void operator()(double d, Gmpz &num, Gmpz &den) const 00450 { 00451 std::pair<double, double> p = split_numerator_denominator(d); 00452 num = Gmpz(p.first); 00453 den = Gmpz(p.second); 00454 } 00455 }; 00456 00457 inline Gmpz min BOOST_PREVENT_MACRO_SUBSTITUTION(const Gmpz& x,const Gmpz& y){ 00458 return (x<=y)?x:y; 00459 } 00460 inline Gmpz max BOOST_PREVENT_MACRO_SUBSTITUTION(const Gmpz& x,const Gmpz& y){ 00461 return (x>=y)?x:y; 00462 } 00463 00464 00465 #include <CGAL/auto_link/GMP.h> 00466 #include <CGAL/auto_link/MPFR.h> 00467 00468 00469 CGAL_END_NAMESPACE 00470 00471 #endif // CGAL_GMPZ_TYPE_H