BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/GMP/Gmpzf_type.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines