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