// 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 #include #include #include #include #ifndef CGAL_CFG_NO_LOCALE # include #else # include #endif #include #include 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 { typedef Handle_for 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(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 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(i, s); } CGAL_END_NAMESPACE #include CGAL_BEGIN_NAMESPACE inline double to_double(const Quotient& 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