BWAPI
|
00001 // Copyright (c) 1997-2001 ETH Zurich (Switzerland). 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/GMP/Gmpzf_type.h $ 00016 // $Id: Gmpzf_type.h 49256 2009-05-09 15:21:26Z spion $ 00017 // 00018 // 00019 // Author(s) : Bernd Gaertner <gaertner@inf.ethz.ch> 00020 00021 #ifndef CGAL_GMPZF_TYPE_H 00022 #define CGAL_GMPZF_TYPE_H 00023 00024 // includes 00025 #include <CGAL/basic.h> 00026 #include <CGAL/Handle_for.h> 00027 #include <gmp.h> 00028 #include <mpfr.h> 00029 #include <CGAL/Quotient.h> 00030 #include <CGAL/GMP/Gmpz_type.h> 00031 #include <boost/operators.hpp> 00032 #include <iostream> 00033 #include <cmath> 00034 #include <limits> 00035 #include <string> 00036 #include <utility> 00037 00038 CGAL_BEGIN_NAMESPACE 00039 00040 //internal fwd 00041 class Gmpzf; 00042 bool operator<(const Gmpzf &a, const Gmpzf &b); 00043 bool operator==(const Gmpzf &a, const Gmpzf &b); 00044 bool operator<(const Gmpzf &a, int b); 00045 bool operator==(const Gmpzf &a, int b); 00046 bool operator>(const Gmpzf &a, int b); 00047 Gmpzf approximate_sqrt(const Gmpzf &f); 00048 00049 struct Gmpzf_rep // as in Gmpz.h 00050 { 00051 // FIXME : bug if ~() is called before an mpz_init*() is called. 00052 // not a problem in practice, but not nice. 00053 // maybe the mpz_init_set* functions should move back to Gmpz_rep. 00054 // But then we should use the Storage_traits::construct/get... 00055 00056 mpz_t mpZ; 00057 00058 Gmpzf_rep() {} 00059 ~Gmpzf_rep() { mpz_clear(mpZ); } 00060 00061 private: 00062 // Make sure it does not get accidentally copied. 00063 Gmpzf_rep(const Gmpzf_rep &); 00064 Gmpzf_rep & operator= (const Gmpzf_rep &); 00065 }; 00066 00067 // class declaration 00068 // ================= 00069 // This is an exact floating point type; it can represent numbers 00070 // of the form m*2^e, where m is of type mpz_t and e (currently) 00071 // of type long 00072 00073 class Gmpzf : 00074 Handle_for<Gmpzf_rep>, 00075 boost::ordered_euclidian_ring_operators1< Gmpzf 00076 , boost::ordered_euclidian_ring_operators2< Gmpzf, int 00077 > > 00078 { 00079 typedef Handle_for<Gmpzf_rep> Base; 00080 00081 public: 00082 00083 // exponent type 00084 // -------------------- 00085 typedef long Exponent; // may overflow, but if it does, the mantissa is 00086 // potentially too large to be useful, anyway; 00087 // still, repeated squaring of a power of two 00088 // quickly brings this type to its limits... 00089 00090 friend Gmpzf approximate_sqrt(const Gmpzf &f); 00091 00092 private: 00093 // data members (mantissa is from Gmpzf_rep) 00094 // ---------------------------------------- 00095 // Invariant: 00096 // - number is in canonical form, i.e.(m,e) == 0 or m is odd 00097 Exponent e; 00098 00099 public: 00100 // access 00101 // ------ 00102 const mpz_t& man() const 00103 { 00104 return Ptr()->mpZ; 00105 } 00106 00107 mpz_t& man() 00108 { 00109 return ptr()->mpZ; 00110 } 00111 00112 const Exponent& exp() const 00113 { 00114 return e; 00115 } 00116 00117 // construction 00118 // ------------ 00119 00120 Gmpzf( ) 00121 : e(0) 00122 { 00123 mpz_init(man()); 00124 CGAL_postcondition(is_canonical()); 00125 } 00126 00127 00128 Gmpzf(const mpz_t z) 00129 : e(0) 00130 { 00131 mpz_init_set(man(), z); 00132 canonicalize(); 00133 } 00134 00135 00136 Gmpzf(const Gmpz& n ) 00137 : e(0) 00138 { 00139 mpz_init_set(man(), n.mpz()); 00140 canonicalize(); 00141 } 00142 00143 00144 Gmpzf( int i) 00145 : e(0) 00146 { 00147 mpz_init_set_si( man(), i); 00148 canonicalize(); 00149 } 00150 00151 Gmpzf( long l) 00152 : e(0) 00153 { 00154 mpz_init_set_si( man(), l); 00155 canonicalize(); 00156 } 00157 00158 Gmpzf( double d) 00159 { 00160 Protect_FPU_rounding<> P(CGAL_FE_TONEAREST); 00161 if (d == 0) { 00162 mpz_init (man()); 00163 e = 0; 00164 return; 00165 } 00166 static int p = std::numeric_limits<double>::digits; 00167 CGAL_assertion(CGAL_NTS is_finite(d) & is_valid(d)); 00168 int exp; 00169 double x = std::frexp(d, &exp); // x in [1/2, 1], x*2^exp = d 00170 mpz_init_set_d (man(), // to the following integer: 00171 std::ldexp( x, p)); 00172 e = exp - p; 00173 canonicalize(); 00174 } 00175 00176 // arithmetics 00177 // ----------- 00178 Gmpzf operator+() const; 00179 Gmpzf operator-() const; 00180 Gmpzf& operator+=( const Gmpzf& b); 00181 Gmpzf& operator+=( int i); 00182 Gmpzf& operator-=( const Gmpzf& b); 00183 Gmpzf& operator-=( int i); 00184 Gmpzf& operator*=( const Gmpzf& b); 00185 Gmpzf& operator*=( int i); 00186 Gmpzf& div(const Gmpzf& b); 00187 Gmpzf& operator%= (const Gmpzf& b); 00188 Gmpzf& div(int i); 00189 Gmpzf& operator%= (int i); 00190 bool is_zero() const; 00191 Sign sign() const; 00192 Gmpzf integral_division(const Gmpzf& b) const; 00193 Gmpzf gcd (const Gmpzf& b) const; 00194 Comparison_result compare (const Gmpzf &b) const; 00195 double to_double() const ; 00196 std::pair<double, double> to_interval() const ; 00197 std::pair<double, long> to_double_exp() const; 00198 std::pair<std::pair<double, double>, long> to_interval_exp() const ; 00199 private: 00200 void canonicalize(); 00201 bool is_canonical() const; 00202 static void align ( const mpz_t*& a_aligned, const mpz_t*& b_aligned, 00203 Exponent& rexp, const Gmpzf& a, const Gmpzf& b); 00204 }; 00205 00206 00207 00208 00209 00210 // implementation 00211 // ============== 00212 00213 // arithmetics 00214 // ----------- 00215 00216 inline 00217 Gmpzf Gmpzf::operator+() const 00218 { 00219 return *this; 00220 } 00221 00222 inline 00223 Gmpzf Gmpzf::operator-() const 00224 { 00225 Gmpzf result; 00226 mpz_neg (result.man(), man()); 00227 result.e = exp(); 00228 CGAL_postcondition(is_canonical()); 00229 return result; 00230 } 00231 00232 inline 00233 Gmpzf& Gmpzf::operator+=( const Gmpzf& b) 00234 { 00235 Gmpzf result; 00236 if (b.is_zero()) return *this; // important in sparse contexts 00237 const mpz_t *a_aligned, *b_aligned; 00238 align (a_aligned, b_aligned, e, *this, b); 00239 mpz_add(result.man(), *a_aligned, *b_aligned); 00240 swap(result); 00241 canonicalize(); 00242 return(*this); 00243 } 00244 00245 inline 00246 Gmpzf& Gmpzf::operator+=( int i) 00247 { 00248 return operator+=(Gmpzf (i)); // could be optimized, but why? 00249 } 00250 00251 inline 00252 Gmpzf& Gmpzf::operator-=( const Gmpzf& b) 00253 { 00254 Gmpzf result; 00255 if (b.is_zero()) return *this; // important in sparse contexts 00256 const mpz_t *a_aligned, *b_aligned; 00257 align (a_aligned, b_aligned, e, *this, b); 00258 mpz_sub(result.man(), *a_aligned, *b_aligned); 00259 swap(result); 00260 canonicalize(); 00261 return(*this); 00262 } 00263 00264 inline 00265 Gmpzf& Gmpzf::operator-=( int i) 00266 { 00267 return operator-=(Gmpzf (i)); // could be optimized, but why? 00268 } 00269 00270 inline 00271 Gmpzf& Gmpzf::operator*=( const Gmpzf& b) 00272 { 00273 Gmpzf result; 00274 mpz_mul(result.man(), man(), b.man()); 00275 e += b.exp(); 00276 swap (result); 00277 canonicalize(); 00278 return *this; 00279 } 00280 00281 inline 00282 Gmpzf& Gmpzf::operator*=( int i) 00283 { 00284 Gmpzf result; 00285 mpz_mul_si(result.man(), man(), i); 00286 swap (result); 00287 canonicalize(); 00288 return *this; 00289 } 00290 00291 // *this = m1 * 2 ^ e1 = a_aligned * 2 ^ rexp 00292 // b = m2 * 2 ^ e2 = b_aligned * 2 ^ rexp, where rexp = min (e1, e2) 00293 // 00294 // => a / b = a div b = (a_aligned div b_aligned) 00295 // a mod b = (a_aligned mod b_aligned) * 2 ^ rexp 00296 inline 00297 Gmpzf& Gmpzf::div(const Gmpzf& b) 00298 { 00299 CGAL_precondition(!b.is_zero()); 00300 Gmpzf result; 00301 const mpz_t *a_aligned, *b_aligned; 00302 align (a_aligned, b_aligned, e, *this, b); 00303 mpz_tdiv_q (result.man(), *a_aligned, *b_aligned); // round towards zero 00304 e = 0; 00305 swap(result); 00306 canonicalize(); 00307 return(*this); 00308 } 00309 00310 inline 00311 Gmpzf& Gmpzf::operator%= (const Gmpzf& b) 00312 { 00313 CGAL_precondition(!b.is_zero()); 00314 Gmpzf result; 00315 const mpz_t *a_aligned, *b_aligned; 00316 align (a_aligned, b_aligned, e, *this, b); 00317 mpz_tdiv_r (result.man(), *a_aligned, *b_aligned); 00318 swap(result); 00319 canonicalize(); 00320 return(*this); 00321 } 00322 00323 inline 00324 Gmpzf& Gmpzf::div(int i) 00325 { 00326 return div(Gmpzf(i)); 00327 } 00328 00329 inline 00330 Gmpzf& Gmpzf::operator%= (int i) 00331 { 00332 return operator%= (Gmpzf(i)); 00333 } 00334 00335 inline 00336 bool Gmpzf::is_zero() const 00337 { 00338 return mpz_sgn( man()) == 0; 00339 } 00340 00341 inline 00342 Sign Gmpzf::sign() const 00343 { 00344 return static_cast<Sign>(mpz_sgn( man())); 00345 } 00346 00347 inline 00348 Gmpzf Gmpzf::integral_division(const Gmpzf& b) const 00349 { 00350 Gmpzf result; 00351 mpz_divexact(result.man(), man(), b.man()); 00352 result.e = exp()-b.exp(); 00353 result.canonicalize(); 00354 CGAL_postcondition (*this == b * result); 00355 return result; 00356 } 00357 00358 inline 00359 Gmpzf Gmpzf::gcd (const Gmpzf& b) const 00360 { 00361 Gmpzf result; 00362 mpz_gcd (result.man(), man(), b.man()); // exponent is 0 00363 result.canonicalize(); 00364 return result; 00365 } 00366 00367 inline 00368 Gmpzf approximate_sqrt(const Gmpzf &f) 00369 { 00370 // is there a well-defined sqrt at all?? Here we do the 00371 // following: write *this as m * 2 ^ e with e even, and 00372 // then return sqrt(m) * 2 ^ (e/2) 00373 Gmpzf result; 00374 // make exponent even 00375 if (f.exp() % 2 == 0) { 00376 mpz_set (result.man(), f.man()); 00377 } else { 00378 mpz_mul_2exp (result.man(), f.man(), 1); 00379 } 00380 mpz_sqrt(result.man(), result.man()); 00381 result.e = f.exp() / 2; 00382 result.canonicalize(); 00383 return result; 00384 } 00385 00386 inline 00387 Comparison_result Gmpzf::compare (const Gmpzf &b) const 00388 { 00389 const mpz_t *a_aligned, *b_aligned; 00390 Exponent rexp; // ignored 00391 align (a_aligned, b_aligned, rexp, *this, b); 00392 int c = mpz_cmp(*a_aligned, *b_aligned); 00393 if (c < 0) return SMALLER; 00394 if (c > 0) return LARGER; 00395 return EQUAL; 00396 } 00397 00398 inline 00399 double Gmpzf::to_double() const 00400 { 00401 Exponent k; // exponent 00402 double l = mpz_get_d_2exp (&k, man()); // mantissa in [0.5,1) 00403 return std::ldexp(l, k+exp()); 00404 } 00405 00406 00407 00408 // internal functions 00409 inline 00410 std::pair<double, long> Gmpzf::to_double_exp() const 00411 { 00412 Exponent k = 0; 00413 double l = mpz_get_d_2exp (&k, man()); 00414 return std::pair<double, long>(l, k+exp()); 00415 } 00416 00417 inline 00418 std::pair<std::pair<double, double>, long> Gmpzf::to_interval_exp() const 00419 { 00420 // get surrounding interval of the form [l * 2 ^ k, u * 2^ k] 00421 // first get mantissa in the form l*2^k, with 0.5 <= d < 1; 00422 // truncation is guaranteed to go towards zero 00423 long k = 0; 00424 double l = mpz_get_d_2exp (&k, man()); 00425 // l = +/- 0.1*...* 00426 // ------ 00427 // 53 digits 00428 // in order to round away from zero, it suffices to add/subtract 2^-53 00429 double u = l; 00430 if (l < 0) 00431 // u is already the upper bound, decrease l to get lower bound 00432 l -= std::ldexp(1.0, -53); 00433 else 00434 // l is already the lower bound, increase u to get upper bound 00435 u += std::ldexp(1.0, -53); 00436 // the interval is now [l * 2^(k + exp()), u * 2^(k + exp())] 00437 // we may cast the exponents to int, since if that's going to 00438 // create an overflow, we correctly get infinities 00439 return std::pair<std::pair<double, double>, long> 00440 (std::pair<double, double>(l, u), k + exp()); 00441 } 00442 00443 inline 00444 std::pair<double, double> Gmpzf::to_interval() const 00445 { 00446 std::pair<std::pair<double, double>, long> lue = to_interval_exp(); 00447 double l = lue.first.first; 00448 double u = lue.first.second; 00449 long k = lue.second; 00450 return std::pair<double,double> (std::ldexp (l, k), std::ldexp (u, k)); 00451 } 00452 00453 inline 00454 void Gmpzf::canonicalize() 00455 { 00456 if (!is_zero()) { 00457 // chop off trailing zeros in m 00458 unsigned long zeros = mpz_scan1(man(), 0); 00459 mpz_tdiv_q_2exp( man(), man(), zeros); // bit-wise right-shift 00460 e += zeros; 00461 } else { 00462 e = 0; 00463 } 00464 CGAL_postcondition(is_canonical()); 00465 } 00466 00467 inline 00468 bool Gmpzf::is_canonical() const 00469 { 00470 return (is_zero() && e==0) || mpz_odd_p (man()); 00471 } 00472 00473 // align a and b such that they have the same exponent: 00474 // a = m1 * 2 ^ e1 -> a_aligned * 2 ^ rexp, 00475 // b = m2 * 2 ^ e2 -> b_aligned * 2 ^ rexp, where rexp = min (e1, e2) 00476 // 00477 // function sets (pointers to) a_aligned and b_aligned and rexp; 00478 // it uses the static s to store the shifted number 00479 inline 00480 void Gmpzf::align ( const mpz_t*& a_aligned, 00481 const mpz_t*& b_aligned, 00482 Exponent& rexp, 00483 const Gmpzf& a, const Gmpzf& b) { 00484 static Gmpz s; 00485 switch (CGAL_NTS compare (b.exp(), a.exp())) { 00486 case SMALLER: 00487 { 00488 // leftshift of a to reach b.exp() 00489 mpz_mul_2exp (s.mpz(), a.man(), a.exp() - b.exp()); 00490 const mpz_t& smpzref = s.mpz(); // leftshifted a 00491 a_aligned = &smpzref; // leftshifted a 00492 const mpz_t& bmanref = b.man(); 00493 b_aligned = &bmanref; // b 00494 rexp = b.exp(); 00495 break; 00496 } 00497 case LARGER: 00498 { 00499 // leftshift of b to reach a.exp() 00500 mpz_mul_2exp (s.mpz(), b.man(), b.exp() - a.exp()); 00501 const mpz_t& amanref = a.man(); 00502 a_aligned = &amanref; // a 00503 const mpz_t& smpzref = s.mpz(); // leftshifted b 00504 b_aligned = &smpzref; // leftshifted b 00505 rexp = a.exp(); 00506 break; 00507 } 00508 case EQUAL: 00509 { 00510 const mpz_t& amanref = a.man(); 00511 a_aligned = &amanref; 00512 const mpz_t& bmanref = b.man(); 00513 b_aligned = &bmanref; 00514 rexp = a.exp(); 00515 } 00516 } 00517 } 00518 00519 // input/output 00520 // ------------ 00521 inline 00522 std::ostream& operator<< (std::ostream& os, const Gmpzf& a) 00523 { 00524 return os << a.to_double(); 00525 } 00526 00527 inline 00528 std::ostream& print (std::ostream& os, const Gmpzf& a) 00529 { 00530 return os << a.man() << "*2^" << a.exp(); 00531 } 00532 00533 inline 00534 std::istream& operator>> ( std::istream& is, Gmpzf& a) 00535 { 00536 // simply read from double 00537 double d; 00538 is >> d; 00539 if (is.good()) 00540 a = Gmpzf(d); 00541 return is; 00542 } 00543 00544 // comparisons 00545 // ----------- 00546 00547 inline 00548 bool operator<(const Gmpzf &a, const Gmpzf &b) 00549 { 00550 return a.compare(b) == SMALLER; 00551 } 00552 00553 inline 00554 bool operator==(const Gmpzf &a, const Gmpzf &b) 00555 { 00556 return ( (mpz_cmp(a.man(), b.man()) == 0) && a.exp() == b.exp() ); 00557 } 00558 00559 // mixed operators 00560 inline 00561 bool operator<(const Gmpzf &a, int b) 00562 { 00563 return operator<(a, Gmpzf(b)); 00564 } 00565 00566 inline 00567 bool operator==(const Gmpzf &a, int b) 00568 { 00569 return operator==(a, Gmpzf(b)); 00570 } 00571 00572 inline 00573 bool operator>(const Gmpzf &a, int b) 00574 { 00575 return operator>(a, Gmpzf(b)); 00576 } 00577 00578 inline Gmpzf min BOOST_PREVENT_MACRO_SUBSTITUTION(const Gmpzf& x,const Gmpzf& y){ 00579 return (x<=y)?x:y; 00580 } 00581 inline Gmpzf max BOOST_PREVENT_MACRO_SUBSTITUTION(const Gmpzf& x,const Gmpzf& y){ 00582 return (x>=y)?x:y; 00583 } 00584 00585 CGAL_END_NAMESPACE 00586 00587 #endif // CGAL_GMPZF_TYPE_H