// Copyright (c) 1999,2003,2004 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/Gmpz.h,v $
// $Revision: 1.39 $ $Date: 2004/09/12 21:12:24 $
// $Name: $
//
// Author(s) : Andreas Fabri, Stefan Schirra, Sylvain Pion
#ifndef CGAL_GMPZ_H
#define CGAL_GMPZ_H
#include <CGAL/basic.h>
#include <CGAL/Handle_for.h>
#include <CGAL/double.h>
#include <CGAL/Interval_arithmetic.h>
#include <string>
#ifndef CGAL_CFG_NO_LOCALE
# include <locale>
#else
# include <cctype>
#endif
#include <gmp.h>
#include <mpfr.h>
CGAL_BEGIN_NAMESPACE
class Gmpz_rep
{
public:
mpz_t mpZ;
Gmpz_rep()
{ mpz_init(mpZ); }
Gmpz_rep(const mpz_t z)
{ mpz_init_set(mpZ, z); }
Gmpz_rep(const Gmpz_rep & g)
{ mpz_init_set(mpZ, g.mpZ); }
Gmpz_rep & operator= (const Gmpz_rep & g)
{
if (&g != this) {
mpz_clear(mpZ);
mpz_init_set(mpZ, g.mpZ);
}
return *this;
}
Gmpz_rep(int si)
{ mpz_init_set_si(mpZ, si); }
Gmpz_rep(long li)
{ mpz_init_set_si(mpZ, li); }
Gmpz_rep(unsigned long li)
{ mpz_init_set_ui(mpZ, li); }
Gmpz_rep(double d)
{ mpz_init_set_d(mpZ, d); }
Gmpz_rep(const char * const str)
{ mpz_init_set_str(mpZ, str, 10); }
Gmpz_rep(const char * const str, int base)
{ mpz_init_set_str(mpZ, str, base); }
~Gmpz_rep()
{ mpz_clear(mpZ); }
};
class Gmpz
: public Handle_for<Gmpz_rep>
{
typedef Handle_for<Gmpz_rep> Base;
public:
typedef Tag_true Has_gcd;
typedef Tag_true Has_division;
typedef Tag_true Has_sqrt;
typedef Tag_true Has_exact_ring_operations;
typedef Tag_false Has_exact_division;
typedef Tag_false Has_exact_sqrt;
Gmpz() // {} we can't do that since the non-const mpz() is called.
: Base(Gmpz_rep()) {}
Gmpz(const mpz_t z)
: Base(Gmpz_rep(z)) {}
Gmpz(int i)
: Base(Gmpz_rep(i)) {}
Gmpz(long l)
: Base(Gmpz_rep(l)) {}
Gmpz(unsigned long l)
: Base(Gmpz_rep(l)) {}
Gmpz(double d)
: Base(Gmpz_rep(d)) {}
Gmpz(const std::string& str)
: Base(Gmpz_rep(str.c_str())) {}
Gmpz(const std::string& str, int base)
: Base(Gmpz_rep(str.c_str(), base)) {}
Gmpz operator-() const;
Gmpz operator%(const Gmpz &z) const;
Gmpz& operator+=(const Gmpz &z);
Gmpz operator+=(int i);
Gmpz& operator-=(const Gmpz &z);
Gmpz operator-=(int i);
Gmpz& operator*=(const Gmpz &z);
Gmpz operator*=(int i);
Gmpz& operator%=(const Gmpz &z);
Gmpz& operator/=(const Gmpz &z);
Gmpz operator/=(int i);
size_t approximate_decimal_length() const;
double to_double() const;
Sign sign() const;
const mpz_t & mpz() const { return Ptr()->mpZ; }
mpz_t & mpz() { return ptr()->mpZ; }
};
inline
bool
operator==(const Gmpz &a, const Gmpz &b)
{ return mpz_cmp(a.mpz(), b.mpz()) == 0; }
inline
bool
operator<(const Gmpz &a, const Gmpz &b)
{ return mpz_cmp(a.mpz(), b.mpz()) < 0; }
inline
bool
operator<=(const Gmpz &a, const Gmpz &b)
{ return ! (b < a); }
inline
bool
operator>(const Gmpz &a, const Gmpz &b)
{ return b < a; }
inline
bool
operator>=(const Gmpz &a, const Gmpz &b)
{ return ! (a < b); }
inline
bool
operator!=(const Gmpz &a, const Gmpz &b)
{ return ! (a == b); }
// mixed operators.
inline
bool
operator<(const Gmpz &a, int b)
{ return mpz_cmp_si(a.mpz(), b) < 0; }
inline
bool
operator<(int a, const Gmpz &b)
{ return mpz_cmp_si(b.mpz(), a) > 0; }
inline
bool
operator==(const Gmpz &a, int b)
{ return mpz_cmp_si(a.mpz(), b) == 0; }
inline
bool
operator==(int a, const Gmpz &b)
{ return b == a; }
inline
bool
operator<=(const Gmpz &a, int b)
{ return ! (b < a); }
inline
bool
operator<=(int a, const Gmpz &b)
{ return ! (b < a); }
inline
bool
operator>(const Gmpz &a, int b)
{ return b < a; }
inline
bool
operator>(int a, const Gmpz &b)
{ return b < a; }
inline
bool
operator>=(const Gmpz &a, int b)
{ return ! (a < b); }
inline
bool
operator>=(int a, const Gmpz &b)
{ return ! (a < b); }
inline
bool
operator!=(const Gmpz &a, int b)
{ return ! (a == b); }
inline
bool
operator!=(int a, const Gmpz &b)
{ return ! (a == b); }
inline
Gmpz
Gmpz::operator-() const
{
Gmpz Res;
mpz_neg(Res.mpz(), mpz());
return Res;
}
inline
Gmpz
operator+(const Gmpz &a, const Gmpz &b)
{
Gmpz Res;
mpz_add(Res.mpz(), a.mpz(), b.mpz());
return Res;
}
inline
Gmpz
operator+(const Gmpz &a, int b)
{
if (b>0)
{
Gmpz Res;
mpz_add_ui(Res.mpz(), a.mpz(), b);
return Res;
}
return a + Gmpz(b);
}
inline
Gmpz&
Gmpz::operator+=(const Gmpz &z)
{
*this = *this + z;
return *this;
}
inline
Gmpz
Gmpz::operator+=(int i)
{
*this = *this + Gmpz(i);
return *this;
}
inline
Gmpz
operator-(const Gmpz &a, const Gmpz &b)
{
Gmpz Res;
mpz_sub(Res.mpz(), a.mpz(), b.mpz());
return Res;
}
inline
Gmpz
operator-(const Gmpz &a, int b)
{
if (b>0)
{
Gmpz Res;
mpz_sub_ui(Res.mpz(), a.mpz(), b);
return Res;
}
return a - Gmpz(b);
}
inline
Gmpz&
Gmpz::operator-=(const Gmpz &z)
{
*this = *this - z;
return *this;
}
inline
Gmpz
Gmpz::operator-=(int i)
{
*this = *this - Gmpz(i);
return *this;
}
inline
Gmpz
operator*(const Gmpz &a, const Gmpz &b)
{
Gmpz Res;
mpz_mul(Res.mpz(), a.mpz(), b.mpz());
return Res;
}
inline
Gmpz
operator*(const Gmpz &a, int b)
{
if (b>0)
{
Gmpz Res;
mpz_mul_ui(Res.mpz(), a.mpz(), b);
return Res;
}
return a * Gmpz(b);
}
inline
Gmpz&
Gmpz::operator*=(const Gmpz &z)
{
*this = *this * z;
return *this;
}
inline
Gmpz
Gmpz::operator*=(int i)
{
*this = *this * Gmpz(i);
return *this;
}
inline
Gmpz
operator/(const Gmpz &a, const Gmpz &b)
{
CGAL_precondition(b != 0);
Gmpz Res;
mpz_tdiv_q(Res.mpz(), a.mpz(), b.mpz());
return Res;
}
inline
Gmpz
operator/(const Gmpz &a, int b)
{
if (b>0)
{
Gmpz Res;
mpz_tdiv_q_ui(Res.mpz(), a.mpz(), b);
return Res;
}
return a / Gmpz(b);
}
inline
Gmpz&
Gmpz::operator/=(const Gmpz &z)
{
*this = *this / z;
return *this;
}
inline
Gmpz
Gmpz::operator/=(int i)
{
*this = *this / Gmpz(i);
return *this;
}
inline
Gmpz
operator+(int i, const Gmpz &z)
{ return z + i; }
inline
Gmpz
operator-(int i, const Gmpz &z)
{ return Gmpz(i) - z; }
inline
Gmpz
operator*(int i, const Gmpz &z)
{ return z * i; }
inline
Gmpz
operator/(int i, const Gmpz &z)
{ return Gmpz(i) / z; }
inline
Gmpz
Gmpz::operator%(const Gmpz &z) const
{
Gmpz Res;
mpz_tdiv_r(Res.mpz(), mpz(), z.mpz());
return Res;
}
inline
Gmpz&
Gmpz::operator%=(const Gmpz &z)
{
*this = *this % z;
return *this;
}
inline
double
Gmpz::to_double() const
{ return mpz_get_d(mpz()); }
inline
io_Operator
io_tag(const Gmpz&)
{ return io_Operator(); }
inline
Sign
Gmpz::sign() const
{ return static_cast<Sign>(mpz_sgn(mpz())); }
inline
double
to_double(const Gmpz &z)
{ return z.to_double(); }
inline
Sign
sign(const Gmpz &z)
{ return z.sign(); }
inline
bool
is_valid(const Gmpz &)
{ return true; }
inline
bool
is_finite(const Gmpz &)
{ return true; }
inline
Gmpz
sqrt(const Gmpz &z)
{
Gmpz Res;
mpz_sqrt(Res.mpz(), z.mpz());
return Res;
}
inline
Gmpz
div(const Gmpz &z1, const Gmpz &z2)
{
return z1 / z2;
}
inline
Gmpz
gcd(const Gmpz &z1, const Gmpz &z2)
{
Gmpz Res;
mpz_gcd(Res.mpz(), z1.mpz(), z2.mpz());
return Res;
}
inline
Gmpz
gcd(const Gmpz &z, int i)
{
if (i > 0)
{
Gmpz Res;
mpz_gcd_ui(Res.mpz(), z.mpz(), i);
return Res;
}
return gcd(z, Gmpz(i));
}
inline
Gmpz
exact_division(const Gmpz &z1, const Gmpz &z2)
{
Gmpz Res;
mpz_divexact(Res.mpz(), z1.mpz(), z2.mpz());
#ifdef CGAL_CHECK_POSTCONDITIONS
mpz_t prod;
mpz_init(prod);
mpz_mul(prod, Res.mpz(), z2.mpz());
CGAL_postcondition_msg(mpz_cmp(prod, z1.mpz()) == 0,
"exact_division failed\n");
mpz_clear( prod);
#endif // CGAL_CHECK_POSTCONDITIONS
return Res;
}
inline
size_t
Gmpz::approximate_decimal_length() const
{ return mpz_sizeinbase(mpz(),10); }
inline
std::ostream&
operator<<(std::ostream& os, const Gmpz &z)
{
char *str = new char [mpz_sizeinbase(z.mpz(),10) + 2];
str = mpz_get_str(str, 10, z.mpz());
os << str ;
delete[] str;
return os;
}
inline
std::istream&
operator>>(std::istream& is, Gmpz &z)
{
bool negative = false;
bool good = false;
const int null = '0';
char c;
Gmpz tmp;
std::ios::fmtflags old_flags = is.flags();
is.unsetf(std::ios::skipws);
#ifndef CGAL_CFG_NO_LOCALE
while (is.get(c) && std::isspace(c, std::locale::classic() ))
#else
while (is.get(c) && CGAL_CLIB_STD::isspace(c))
#endif // CGAL_CFG_NO_LOCALE
{}
if (c == '-')
{
negative = true;
#ifndef CGAL_CFG_NO_LOCALE
while (is.get(c) && std::isspace(c, std::locale::classic() ))
#else
while (is.get(c) && CGAL_CLIB_STD::isspace(c))
#endif // CGAL_CFG_NO_LOCALE
{}
}
#ifndef CGAL_CFG_NO_LOCALE
if (std::isdigit(c, std::locale::classic() ))
#else
if (std::isdigit(c))
#endif // CGAL_CFG_NO_LOCALE
{
good = true;
tmp = c - null;
#ifndef CGAL_CFG_NO_LOCALE
while (is.get(c) && std::isdigit(c, std::locale::classic() ))
#else
while (is.get(c) && std::isdigit(c))
#endif // CGAL_CFG_NO_LOCALE
{
tmp = 10*tmp + (c-null);
}
}
if (is)
is.putback(c);
if (sign(tmp) != ZERO && negative)
tmp = -tmp;
if (good){
z = tmp;
}
else
is.clear(is.rdstate() | std::ios::failbit);
is.flags(old_flags);
return is;
}
inline
std::pair<double, double>
to_interval (const Gmpz & z)
{
mpfr_t x;
mpfr_init2 (x, 53); /* Assume IEEE-754 */
mpfr_set_z (x, z.mpz(), GMP_RNDD);
double i = mpfr_get_d (x, GMP_RNDD); /* EXACT but can overflow */
mpfr_set_z (x, z.mpz(), GMP_RNDU);
double s = mpfr_get_d (x, GMP_RNDU); /* EXACT but can overflow */
mpfr_clear (x);
return std::pair<double, double>(i, s);
}
CGAL_END_NAMESPACE
#include <CGAL/Quotient.h>
CGAL_BEGIN_NAMESPACE
inline
double to_double(const Quotient<Gmpz>& quot)
{
mpq_t mpQ;
mpq_init(mpQ);
const Gmpz& n = quot.numerator();
const Gmpz& d = quot.denominator();
mpz_set(mpq_numref(mpQ), n.mpz());
mpz_set(mpq_denref(mpQ), d.mpz());
mpq_canonicalize(mpQ);
double ret = mpq_get_d(mpQ);
mpq_clear(mpQ);
return ret;
}
CGAL_END_NAMESPACE
#endif // CGAL_GMPZ_H
syntax highlighted by Code2HTML, v. 0.9.1