// 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 <CGAL/basic.h>
#include <CGAL/Handle_for.h>
#include <CGAL/Gmpz.h>
#include <CGAL/Interval_arithmetic.h>
#include <utility>
#include <string>
#include <gmp.h>
#include <mpfr.h>
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<Gmpq_rep>
{
typedef Handle_for<Gmpq_rep> 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<Sign>(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<double, double>
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<double, double>(i, s);
}
template <>
struct Rational_traits<Gmpq> {
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
syntax highlighted by Code2HTML, v. 0.9.1