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