// Copyright (c) 2002,2003 Utrecht University (The Netherlands), // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany), // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria), // and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; version 2.1 of the License. // See the file LICENSE.LGPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $Source: /CVSROOT/CGAL/Packages/Number_types/include/CGAL/Gmpq.h,v $ // $Revision: 1.19 $ $Date: 2004/09/01 16:17:11 $ // $Name: $ // // Author(s) : Andreas Fabri, Sylvain Pion #ifndef CGAL_GMPQ_H #define CGAL_GMPQ_H #include #include #include #include #include #include #include #include CGAL_BEGIN_NAMESPACE class Gmpq_rep { public: mpq_t mpQ; Gmpq_rep() { mpq_init(mpQ); } Gmpq_rep(const mpq_t z) { mpq_init(mpQ); mpq_set(mpQ, z); } Gmpq_rep(const Gmpq_rep & g) { mpq_init(mpQ); mpq_set(mpQ, g.mpQ); } Gmpq_rep & operator= (const Gmpq_rep & g) { if (&g != this) { mpq_clear(mpQ); mpq_set(mpQ, g.mpQ); } return *this; } Gmpq_rep(int si) { mpq_init(mpQ); mpq_set_si(mpQ, si, 1); } Gmpq_rep(long si) { mpq_init(mpQ); mpq_set_si(mpQ, si, 1); } Gmpq_rep(unsigned long ui) { mpq_init(mpQ); mpq_set_ui(mpQ, ui, 1); } Gmpq_rep(const Gmpz& z) { mpq_init(mpQ); mpq_set_z(mpQ, z.mpz()); } Gmpq_rep(unsigned long int ui1, unsigned long int ui2) { mpq_init(mpQ); mpq_set_ui(mpQ, ui1, ui2); mpq_canonicalize(mpQ); } Gmpq_rep(signed long int si, unsigned long int ui) { mpq_init(mpQ); mpq_set_si(mpQ, si, ui); mpq_canonicalize(mpQ); } Gmpq_rep(int num, int den) { mpq_init(mpQ); if(den < 0) { num = -num; den = -den; } mpq_set_si(mpQ, num, den); mpq_canonicalize(mpQ); } Gmpq_rep(const Gmpz& n, const Gmpz& d) { mpq_init(mpQ); mpz_set(mpq_numref(mpQ), n.mpz()); mpz_set(mpq_denref(mpQ), d.mpz()); mpq_canonicalize(mpQ); } Gmpq_rep(double d) { mpq_init(mpQ); mpq_set_d(mpQ, d); } Gmpq_rep(const std::string& str) { mpq_init(mpQ); mpq_set_str(mpQ, str.c_str(), 10); mpq_canonicalize(mpQ); } Gmpq_rep(const std::string& str, int base) { mpq_init(mpQ); mpq_set_str(mpQ, str.c_str(), base); mpq_canonicalize(mpQ); } ~Gmpq_rep() { mpq_clear(mpQ); } }; class Gmpq : public Handle_for { typedef Handle_for Base; public: typedef Tag_false Has_gcd; typedef Tag_true Has_division; typedef Tag_false Has_sqrt; typedef Tag_true Has_exact_ring_operations; typedef Tag_true Has_exact_division; typedef Tag_false Has_exact_sqrt; Gmpq() // {} we can't do that since the non-const mpq() is called. : Base(Gmpq_rep()) {} Gmpq(const mpq_t z) : Base(Gmpq_rep(z)) {} Gmpq(int n) : Base(Gmpq_rep(n)) {} Gmpq(long n) : Base(Gmpq_rep(n)) {} Gmpq(unsigned long n) : Base(Gmpq_rep(n)) {} Gmpq(const Gmpz& n) : Base(Gmpq_rep(n)) {} Gmpq(int n, int d) : Base(Gmpq_rep(n, d)) {} Gmpq(signed long n, unsigned long d) : Base(Gmpq_rep(n, d)) {} Gmpq(unsigned long n, unsigned long d) : Base(Gmpq_rep(n, d)) {} Gmpq(const Gmpz& n, const Gmpz& d) : Base(Gmpq_rep(n,d)) {} Gmpq(double d) : Base(Gmpq_rep(d)) {} Gmpq(const std::string& str) : Base(Gmpq_rep(str)) {} Gmpq(const std::string& str, int base) : Base(Gmpq_rep(str, base)) {} Gmpz numerator() const { return Gmpz(mpq_numref(mpq())); } Gmpz denominator() const { return Gmpz(mpq_denref(mpq())); } Gmpq operator-() const; Gmpq& operator+=(const Gmpq &z); Gmpq& operator-=(const Gmpq &z); Gmpq& operator*=(const Gmpq &z); Gmpq& operator/=(const Gmpq &z); double to_double() const; Sign sign() const; const mpq_t & mpq() const { return Ptr()->mpQ; } mpq_t & mpq() { return ptr()->mpQ; } }; inline bool operator==(const Gmpq &a, const Gmpq &b) { return mpq_equal(a.mpq(), b.mpq()); } inline bool operator<(const Gmpq &a, const Gmpq &b) { return mpq_cmp(a.mpq(), b.mpq()) < 0; } inline bool operator<=(const Gmpq &a, const Gmpq &b) { return ! (b < a); } inline bool operator>(const Gmpq &a, const Gmpq &b) { return b < a; } inline bool operator>=(const Gmpq &a, const Gmpq &b) { return ! (a < b); } inline bool operator!=(const Gmpq &a, const Gmpq &b) { return ! (a == b); } // mixed operators. inline bool operator<(const Gmpq &a, int b) { return mpq_cmp_si(a.mpq(), b, 1) < 0; } inline bool operator<(int a, const Gmpq &b) { return mpq_cmp_si(b.mpq(), a, 1) > 0; } inline bool operator==(const Gmpq &a, int b) { return mpq_cmp_si(a.mpq(), b, 1) == 0; } inline bool operator==(int a, const Gmpq &b) { return b == a; } inline bool operator<=(const Gmpq &a, int b) { return ! (b < a); } inline bool operator<=(int a, const Gmpq &b) { return ! (b < a); } inline bool operator>(const Gmpq &a, int b) { return b < a; } inline bool operator>(int a, const Gmpq &b) { return b < a; } inline bool operator>=(const Gmpq &a, int b) { return ! (a < b); } inline bool operator>=(int a, const Gmpq &b) { return ! (a < b); } inline bool operator!=(const Gmpq &a, int b) { return ! (a == b); } inline bool operator!=(int a, const Gmpq &b) { return ! (a == b); } inline Gmpq Gmpq::operator-() const { Gmpq Res; mpq_neg(Res.mpq(), mpq()); return Res; } inline Gmpq operator+(const Gmpq &a, const Gmpq &b) { Gmpq Res; mpq_add(Res.mpq(), a.mpq(), b.mpq()); return Res; } inline Gmpq& Gmpq::operator+=(const Gmpq &z) { *this = *this + z; return *this; } inline Gmpq operator-(const Gmpq &a, const Gmpq &b) { Gmpq Res; mpq_sub(Res.mpq(), a.mpq(), b.mpq()); return Res; } inline Gmpq& Gmpq::operator-=(const Gmpq &z) { *this = *this - z; return *this; } inline Gmpq operator*(const Gmpq &a, const Gmpq &b) { Gmpq Res; mpq_mul(Res.mpq(), a.mpq(), b.mpq()); return Res; } inline Gmpq& Gmpq::operator*=(const Gmpq &z) { *this = *this * z; return *this; } inline Gmpq operator/(const Gmpq &a, const Gmpq &b) { CGAL_precondition(b != 0); Gmpq Res; mpq_div(Res.mpq(), a.mpq(), b.mpq()); return Res; } inline Gmpq& Gmpq::operator/=(const Gmpq &z) { *this = *this / z; return *this; } inline double Gmpq::to_double() const { return mpq_get_d(mpq()); } inline io_Operator io_tag(const Gmpq&) { return io_Operator(); } inline Sign Gmpq::sign() const { return static_cast(mpq_sgn(mpq())); } inline double to_double(const Gmpq &z) { return z.to_double(); } inline Sign sign(const Gmpq &z) { return z.sign(); } inline bool is_valid(const Gmpq &) { return true; } inline bool is_finite(const Gmpq &) { return true; } inline std::ostream& operator<<(std::ostream& os, const Gmpq &z) { os << z.numerator() << "/" << z.denominator(); return os; } inline std::istream& operator>>(std::istream& is, Gmpq &z) { char c; Gmpz n, d; is >> n; is >> c; CGAL_assertion(!is || c == '/'); is >> d; if (is) z = Gmpq(n,d); return is; } inline std::pair to_interval (const Gmpq& z) { mpfr_t x; mpfr_init2 (x, 53); /* Assume IEEE-754 */ mpfr_set_q (x, z.mpq(), GMP_RNDD); double i = mpfr_get_d (x, GMP_RNDD); /* EXACT but can overflow */ mpfr_set_q (x, z.mpq(), GMP_RNDU); double s = mpfr_get_d (x, GMP_RNDU); /* EXACT but can overflow */ mpfr_clear (x); return std::pair(i, s); } template <> struct Rational_traits { typedef Gmpz RT; RT numerator (const Gmpq & r) const { return r.numerator(); } RT denominator (const Gmpq & r) const { return r.denominator(); } Gmpq make_rational (const RT & n, const RT & d) const { return Gmpq(n, d); } }; CGAL_END_NAMESPACE #endif // CGAL_GMPQ_H