BWAPI
|
00001 // Copyright (c) 2002,2003 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/Gmpq_type.h $ 00019 // $Id: Gmpq_type.h 49008 2009-04-29 13:57:45Z hemmer $ 00020 // 00021 // 00022 // Author(s) : Andreas Fabri, Sylvain Pion 00023 00024 00025 #ifndef CGAL_GMPQ_TYPE_H 00026 #define CGAL_GMPQ_TYPE_H 00027 00028 #include <CGAL/basic.h> 00029 #include <CGAL/GMP/Gmpz_type.h> 00030 00031 #include <gmp.h> 00032 #include <mpfr.h> 00033 #include <utility> 00034 #include <string> 00035 00036 #include <boost/operators.hpp> 00037 #include <CGAL/Handle_for.h> 00038 #include <CGAL/Profile_counter.h> 00039 00040 00041 CGAL_BEGIN_NAMESPACE 00042 // TODO : add mixed operators with Gmpz. 00043 00044 // Wrapper around mpq_t to get the destructor call mpq_clear. 00045 // Contrary to mpz_t, there are no mpq_init_set_* functions, 00046 // so we simply call mpq_init() here. 00047 struct Gmpq_rep 00048 { 00049 mpq_t mpQ; 00050 00051 Gmpq_rep() { mpq_init(mpQ); } 00052 ~Gmpq_rep() { mpq_clear(mpQ); } 00053 00054 private: 00055 // Make sure it does not get accidentally copied. 00056 Gmpq_rep(const Gmpq_rep &); 00057 Gmpq_rep & operator= (const Gmpq_rep &); 00058 }; 00059 00060 00061 class Gmpq 00062 : Handle_for<Gmpq_rep>, 00063 boost::ordered_field_operators1< Gmpq 00064 , boost::ordered_field_operators2< Gmpq, int 00065 > > 00066 { 00067 typedef Handle_for<Gmpq_rep> Base; 00068 public: 00069 typedef Tag_false Has_gcd; 00070 typedef Tag_true Has_division; 00071 typedef Tag_false Has_sqrt; 00072 00073 typedef Tag_true Has_exact_ring_operations; 00074 typedef Tag_true Has_exact_division; 00075 typedef Tag_false Has_exact_sqrt; 00076 00077 Gmpq() {} 00078 00079 Gmpq(const mpq_t q) 00080 { mpq_set(mpq(), q); } 00081 00082 Gmpq(int n) 00083 { mpq_set_si(mpq(), n, 1); } 00084 00085 Gmpq(long n) 00086 { mpq_set_si(mpq(), n, 1); } 00087 00088 Gmpq(unsigned long n) 00089 { mpq_set_ui(mpq(), n, 1); } 00090 00091 Gmpq(const Gmpz& n) 00092 { mpq_set_z(mpq(), n.mpz()); } 00093 00094 Gmpq(int n, int d) 00095 { 00096 if (d < 0) { 00097 n = -n; 00098 d = -d; 00099 } 00100 mpq_set_si(mpq(), n, d); 00101 mpq_canonicalize(mpq()); 00102 } 00103 00104 Gmpq(signed long n, unsigned long d) 00105 { 00106 mpq_set_si(mpq(), n, d); 00107 mpq_canonicalize(mpq()); 00108 } 00109 00110 Gmpq(unsigned long n, unsigned long d) 00111 { 00112 mpq_set_ui(mpq(), n, d); 00113 mpq_canonicalize(mpq()); 00114 } 00115 00116 Gmpq(const Gmpz& n, const Gmpz& d) 00117 { 00118 mpz_set(mpq_numref(mpq()), n.mpz()); 00119 mpz_set(mpq_denref(mpq()), d.mpz()); 00120 mpq_canonicalize(mpq()); 00121 } 00122 00123 Gmpq(double d) 00124 { 00125 CGAL_assertion(is_finite(d)); 00126 mpq_set_d(mpq(), d); 00127 } 00128 00129 Gmpq(const std::string& str, int base = 10) 00130 { 00131 mpq_set_str(mpq(), str.c_str(), base); 00132 mpq_canonicalize(mpq()); 00133 } 00134 00135 #ifdef CGAL_ROOT_OF_2_ENABLE_HISTOGRAM_OF_NUMBER_OF_DIGIT_ON_THE_COMPLEX_CONSTRUCTOR 00136 int tam() const { return 0; } // put here a code 00137 // measuring the number of digits 00138 // of the Gmpq 00139 // a possible code is: 00140 // int tam() const { return std::max(numerator().tam(), 00141 // denominator().tam()); } 00142 // the same as Quotient<MP_Float> 00143 #endif 00144 00145 // Gives the memory size in bytes. (not documented yet) 00146 std::size_t size() const 00147 { 00148 std::size_t s_num = mpz_size(mpq_numref(mpq())) * (mp_bits_per_limb/8); 00149 std::size_t s_den = mpz_size(mpq_denref(mpq())) * (mp_bits_per_limb/8); 00150 return s_num + s_den; 00151 } 00152 00153 Gmpz numerator() const 00154 { return Gmpz(mpq_numref(mpq())); } 00155 00156 Gmpz denominator() const 00157 { return Gmpz(mpq_denref(mpq())); } 00158 00159 Gmpq operator+() const; 00160 Gmpq operator-() const; 00161 00162 Gmpq& operator+=(const Gmpq &z); 00163 Gmpq& operator-=(const Gmpq &z); 00164 Gmpq& operator*=(const Gmpq &z); 00165 Gmpq& operator/=(const Gmpq &z); 00166 00167 double to_double() const; 00168 Sign sign() const; 00169 00170 const mpq_t & mpq() const { return Ptr()->mpQ; } 00171 mpq_t & mpq() { return ptr()->mpQ; } 00172 00173 ~Gmpq() 00174 { 00175 CGAL_HISTOGRAM_PROFILER("[Gmpq sizes in log2 scale]", 00176 (unsigned) ( ::log(double(size())) / ::log(double(2)) ) ); 00177 } 00178 }; 00179 00180 00181 inline 00182 bool 00183 operator==(const Gmpq &a, const Gmpq &b) 00184 { return mpq_equal(a.mpq(), b.mpq()) != 0; } 00185 00186 inline 00187 bool 00188 operator<(const Gmpq &a, const Gmpq &b) 00189 { return mpq_cmp(a.mpq(), b.mpq()) < 0; } 00190 00191 00192 // mixed operators. 00193 inline 00194 bool 00195 operator<(const Gmpq &a, int b) 00196 { return mpq_cmp_si(a.mpq(), b, 1) < 0; } 00197 00198 inline 00199 bool 00200 operator>(const Gmpq &a, int b) 00201 { return mpq_cmp_si(a.mpq(), b, 1) > 0; } 00202 00203 inline 00204 bool 00205 operator==(const Gmpq &a, int b) 00206 { return mpq_cmp_si(a.mpq(), b, 1) == 0; } 00207 00208 00209 inline 00210 Gmpq 00211 Gmpq::operator-() const 00212 { 00213 Gmpq Res; 00214 mpq_neg(Res.mpq(), mpq()); 00215 return Res; 00216 } 00217 00218 inline 00219 Gmpq 00220 Gmpq::operator+() const 00221 { 00222 return Gmpq(mpq()); 00223 } 00224 00225 inline 00226 Gmpq& 00227 Gmpq::operator+=(const Gmpq &z) 00228 { 00229 Gmpq Res; 00230 mpq_add(Res.mpq(), mpq(), z.mpq()); 00231 swap(Res); 00232 return *this; 00233 } 00234 00235 inline 00236 Gmpq& 00237 Gmpq::operator-=(const Gmpq &z) 00238 { 00239 Gmpq Res; 00240 mpq_sub(Res.mpq(), mpq(), z.mpq()); 00241 swap(Res); 00242 return *this; 00243 } 00244 00245 inline 00246 Gmpq& 00247 Gmpq::operator*=(const Gmpq &z) 00248 { 00249 Gmpq Res; 00250 mpq_mul(Res.mpq(), mpq(), z.mpq()); 00251 swap(Res); 00252 return *this; 00253 } 00254 00255 inline 00256 Gmpq& 00257 Gmpq::operator/=(const Gmpq &z) 00258 { 00259 CGAL_precondition(z != 0); 00260 Gmpq Res; 00261 mpq_div(Res.mpq(), mpq(), z.mpq()); 00262 swap(Res); 00263 return *this; 00264 } 00265 00266 inline 00267 double 00268 Gmpq::to_double() const 00269 { return mpq_get_d(mpq()); } 00270 00271 00272 inline 00273 Sign 00274 Gmpq::sign() const 00275 { return static_cast<Sign>(mpq_sgn(mpq())); } 00276 00277 inline 00278 std::ostream& 00279 operator<<(std::ostream& os, const Gmpq &z) 00280 { 00281 os << z.numerator() << "/" << z.denominator(); 00282 return os; 00283 } 00284 00285 // inline 00286 // std::istream& 00287 // operator>>(std::istream& is, Gmpq &z) 00288 // { 00289 // char c; 00290 // Gmpz n, d; 00291 // is >> n; 00292 // is >> c; 00293 // //CGAL_assertion(!is || c == '/'); 00294 // if (c != '/'){ 00295 // is.setstate(std::ios_base::failbit); 00296 // return is; 00297 // } 00298 // is >> d; 00299 // if (!is.fail()) { 00300 // z = Gmpq(n,d); 00301 // } 00302 // return is; 00303 // } 00304 00305 namespace Gmpq_detail { 00306 inline 00307 bool is_space (const std::istream& /*is*/, std::istream::int_type c) 00308 { 00309 std::istream::char_type cc= c; 00310 return (c == std::istream::traits_type::eof()) || 00311 std::isspace(cc, std::locale::classic() ); 00312 } 00313 00314 inline 00315 bool is_eof (const std::istream& /*is*/, std::istream::int_type c) 00316 { 00317 return c == std::istream::traits_type::eof(); 00318 } 00319 00320 inline 00321 bool is_digit (const std::istream& /*is*/, std::istream::int_type c) 00322 { 00323 std::istream::char_type cc= c; 00324 return std::isdigit(cc, std::locale::classic() ); 00325 } 00326 } 00327 00328 inline 00329 std::istream& 00330 operator>>(std::istream& is, Gmpq &z) 00331 { 00332 // reads rational and floating point literals. 00333 const std::istream::char_type zero = '0'; 00334 std::istream::int_type c; 00335 std::ios::fmtflags old_flags = is.flags(); 00336 00337 is.unsetf(std::ios::skipws); 00338 gmpz_eat_white_space(is); 00339 00340 Gmpz n(0); // unsigned number before '/' or '.' 00341 Gmpz d(1); // number after '/', or denominator (fp-case) 00342 bool negative = false; // do we have a leading '-'? 00343 bool digits = false; // for fp-case: are there any digits at all? 00344 00345 c = is.peek(); 00346 if (c != '.') { 00347 // is there a sign? 00348 if (c == '-' || c == '+') { 00349 is.get(); 00350 negative = (c == '-'); 00351 gmpz_eat_white_space(is); 00352 c=is.peek(); 00353 } 00354 // read n (could be empty) 00355 while (!Gmpq_detail::is_eof(is, c) && Gmpq_detail::is_digit(is, c)) { 00356 digits = true; 00357 n = n*10 + (c-zero); 00358 is.get(); 00359 c = is.peek(); 00360 } 00361 // are we done? 00362 if (Gmpq_detail::is_eof(is, c) || Gmpq_detail::is_space(is, c)) { 00363 is.flags(old_flags); 00364 if (digits && !is.fail()) 00365 z = negative? Gmpq(-n,1): Gmpq(n,1); 00366 return is; 00367 } 00368 } else 00369 n = 0; 00370 00371 // now we have read n, we are not done, and c is the next character 00372 // in the stream 00373 if (c == '/' || c == '.') { 00374 is.get(); 00375 if (c == '/') { 00376 // rational case 00377 is >> d; 00378 is.flags(old_flags); 00379 if (!is.fail()) 00380 z = negative? Gmpq(-n,d): Gmpq(n,d); 00381 return is; 00382 } 00383 00384 // floating point case; read number after '.' (may be empty) 00385 while (true) { 00386 c = is.peek(); 00387 if (Gmpq_detail::is_eof(is, c) || !Gmpq_detail::is_digit(is, c)) 00388 break; 00389 // now we have a digit 00390 is.get(); 00391 digits = true; 00392 d *= 10; 00393 n = n*10 + (c-zero); 00394 } 00395 } 00396 00397 // now we have read all digits after '.', and c is the next character; 00398 // read the exponential part (optional) 00399 int e = 0; 00400 if (c == 'e' || c == 'E') { 00401 is.get(); 00402 is >> e; 00403 } 00404 00405 // now construct the Gmpq 00406 if (!digits) { 00407 // illegal floating-point number 00408 is.setstate(std::ios_base::failbit); 00409 is.flags(old_flags); 00410 return is; 00411 } 00412 00413 // handle e 00414 if (e > 0) 00415 while (e--) n *= 10; 00416 else 00417 while (e++) d *= 10; 00418 is.flags(old_flags); 00419 if (!is.fail()) 00420 z = (negative ? Gmpq(-n,d) : Gmpq(n,d)); 00421 return is; 00422 } 00423 00424 inline Gmpq min BOOST_PREVENT_MACRO_SUBSTITUTION(const Gmpq& x,const Gmpq& y){ 00425 return (x<=y)?x:y; 00426 } 00427 inline Gmpq max BOOST_PREVENT_MACRO_SUBSTITUTION(const Gmpq& x,const Gmpq& y){ 00428 return (x>=y)?x:y; 00429 } 00430 00431 00432 CGAL_END_NAMESPACE 00433 00434 00435 #endif // CGAL_GMPQ_TYPE_H