/**************************************************************************** * Core Library Version 1.7, August 2004 * Copyright (c) 1995-2004 Exact Computation Project * All rights reserved. * * This file is part of CGAL (www.cgal.org). * * File: BigInt.h * Synopsis: * a wrapper class for mpz from GMP * * Written by * Chee Yap * Chen Li * Zilin Du * * WWW URL: http://cs.nyu.edu/exact/ * Email: exact@cs.nyu.edu * * $URL$ * $Id$ * SPDX-License-Identifier: LGPL-3.0-or-later ***************************************************************************/ #ifndef _CORE_BIGINT_H_ #define _CORE_BIGINT_H_ #include #include #include #include #include #if 1 namespace CORE { #ifdef CGAL_CORE_USE_GMP_BACKEND typedef boost::multiprecision::mpz_int BigInt; #else typedef boost::multiprecision::cpp_int BigInt; #endif inline int cmp(const BigInt& x, const BigInt& y) { return x.compare(y); } int set_str(BigInt& a, const char* s) { // AF makeCopy(); a = BigInt(s); return 0; // should be -1 if not correct in the base (we ignore) } /// longValue inline long longValue(const BigInt& a) { return a.convert_to();; } /// doubleValue inline double doubleValue(const BigInt& a) { return a.convert_to();; } /// isEven inline bool isEven(const BigInt& z) { return bit_test(z,0) == 0; } /// isOdd inline bool isOdd(const BigInt& z) { return bit_test(z,0) == 1; } inline bool isDivisible(const BigInt& x, const BigInt& y) { BigInt q, r; divide_qr(x, y, q, r); return r.is_zero(); } inline bool isDivisible(int x, int y) { return x % y == 0; } inline bool isDivisible(long x, long y) { return x % y == 0; } /// get exponent of power 2 inline unsigned long getBinExpo(const BigInt& z) { if (z.is_zero()) { return (std::numeric_limits::max)(); } return lsb(abs(z)); } // bit length inline int bitLength(const BigInt& a) { if (a.is_zero()) { return 0; } return msb(abs(a))+1; } /// floorLg -- floor of log_2(a) /** Convention: a=0, floorLg(a) returns -1. * This makes sense for integer a. */ inline long floorLg(const BigInt& a) { return (sign(a) == 0) ? (-1) : (bitLength(a)-1); } /// div_rem inline void div_rem(BigInt& q, BigInt& r, const BigInt& a, const BigInt& b) { // AF q.makeCopy(); // AF r.makeCopy(); divide_qr(a, b, q, r); } /// ulongValue inline unsigned long ulongValue(const BigInt& a) { assert(a >= BigInt(0)); return a.convert_to(); } /// exact div inline void divexact(BigInt& z, const BigInt& x, const BigInt& y) { // AF z.makeCopy(); BigInt r; divide_qr(x, y, z, r ); // was void mpz_divexact (mpz_t q, const mpz_t n, const mpz_t d) Is this faster? assert(r.is_zero()); } // Chee (1/12/2004) The definition of div_exact(x,y) next // ensure that in Polynomials works with both NT=BigInt and NT=int: inline BigInt div_exact(const BigInt& x, const BigInt& y) { BigInt z; // precodition: isDivisible(x,y) divexact(z, x, y); // z is set to x/y; return z; } inline int div_exact(int x, int y) { return x/y; // precondition: isDivisible(x,y) } inline long div_exact(long x, long y) { return x/y; // precondition: isDivisible(x,y) } /// ceilLg -- ceiling of log_2(a) where a=BigInt, int or long /** Convention: a=0, ceilLg(a) returns -1. * This makes sense for integer a. */ inline long ceilLg(const BigInt& a) { if (sign(a) == 0) return -1; unsigned long len = bitLength(a); return (lsb(abs(a)) == len - 1) ? (len - 1) : len; } inline long ceilLg(long a) { // need this for Polynomial return ceilLg(BigInt(a)); } inline long ceilLg(int a) { // need this for Polynomial return ceilLg(BigInt(a)); } /// negate inline void negate(BigInt& a) { // AF a.makeCopy(); a= - a; } /// get exponent of power k inline void getKaryExpo(const BigInt& z, BigInt& m, int& e, unsigned long uk) { BigInt k(uk), q, r; e = 0; m = z; // AF m.makeCopy(); for(;;) { divide_qr(m, k, q, r); if (!r.is_zero()) break; m = q; ++e; } } inline void power(BigInt& c, const BigInt& a, unsigned long ul) { // AF c.makeCopy(); c = pow(a, ul); } } // namespace CORE #else namespace CORE { #ifdef CGAL_CORE_USE_GMP_BACKEND typedef boost::multiprecision::mpz_int Z; #else typedef boost::multiprecision::cpp_int Z; #endif class BigIntRep : public RCRepImpl { public: BigIntRep() : mp() {} // Note : should the copy-ctor be allowed at all ? [Sylvain Pion] BigIntRep(const BigIntRep& z) : RCRepImpl(), mp(z.mp) {} template BigIntRep(T c) : mp(c) {} BigIntRep(const std::string& s) : mp(s) {} explicit BigIntRep(const Z& z) : mp(z) {} /* ~BigIntRep() { mpz_clear(mp); } */ //CGAL_CORE_EXPORT CORE_NEW(BigIntRep) //CGAL_CORE_EXPORT CORE_DELETE(BigIntRep) const Z& get_mp() const { return mp; } Z& get_mp() { return mp; } private: Z mp; }; //typedef RCImpl RCBigInt; class CGAL_CORE_EXPORT BigInt : public RCImpl { public: typedef RCImpl RCBigInt; /// \name Constructors //@{ /// default constructor BigInt() : RCBigInt(new BigIntRep()) {} BigInt(const Z& z) : RCBigInt(new BigIntRep(z)) {} /// constructor for signed char BigInt(signed char x) : RCBigInt(new BigIntRep(x)) {} /// constructor for unsigned char BigInt(unsigned char x) : RCBigInt(new BigIntRep(x)) {} /// constructor for signed short int BigInt(signed short int x) : RCBigInt(new BigIntRep(x)) {} /// constructor for unsigned short int BigInt(unsigned short int x) : RCBigInt(new BigIntRep(x)) {} /// constructor for signed int BigInt(signed int x) : RCBigInt(new BigIntRep(x)) {} /// constructor for unsigned int BigInt(unsigned int x) : RCBigInt(new BigIntRep(x)) {} /// constructor for signed long int BigInt(signed long int x) : RCBigInt(new BigIntRep(x)) {} /// constructor for unsigned long int BigInt(unsigned long int x) : RCBigInt(new BigIntRep(x)) {} /// constructor for float BigInt(float x) : RCBigInt(new BigIntRep(x)) {} /// constructor for double BigInt(double x) : RCBigInt(new BigIntRep(x)) {} /// constructor for std::string BigInt(const std::string& s) : RCBigInt(new BigIntRep(s)) {} /// constructor for mpz_srcptr // explicit BigInt(mpz_srcptr z) : RCBigInt(new BigIntRep(z)) {} //@} /// \name Copy-Assignment-Destructor //@{ /// copy constructor BigInt(const BigInt& rhs) : RCBigInt(rhs) { rep->incRef(); } /// assignment operator BigInt& operator=(const BigInt& rhs) { if (this != &rhs) { rep->decRef(); rep = rhs.rep; rep->incRef(); } return *this; } /// destructor ~BigInt() { rep->decRef(); } //@} /// \name Overloaded operators //@{ BigInt& operator +=(const BigInt& rhs) { makeCopy(); get_mp() += rhs.get_mp(); return *this; } BigInt& operator -=(const BigInt& rhs) { makeCopy(); get_mp() -= rhs.get_mp(); return *this; } BigInt& operator *=(const BigInt& rhs) { makeCopy(); get_mp() *= rhs.get_mp(); return *this; } BigInt& operator /=(const BigInt& rhs) { makeCopy(); get_mp() /= rhs.get_mp(); return *this; } BigInt& operator %=(const BigInt& rhs) { makeCopy(); get_mp() %= rhs.get_mp(); return *this; } BigInt& operator &=(const BigInt& rhs) { makeCopy(); get_mp() &= rhs.get_mp(); return *this; } BigInt& operator |=(const BigInt& rhs) { makeCopy(); get_mp() |= rhs.get_mp(); return *this; } BigInt& operator ^=(const BigInt& rhs) { makeCopy(); get_mp() ^= rhs.get_mp(); return *this; } BigInt& operator <<=(unsigned long ul) { makeCopy(); get_mp() <<= ul; return *this; } BigInt& operator >>=(unsigned long ul) { makeCopy(); get_mp() >>= ul; return *this; } //@} /// \name unary, increment, decrement operators //@{ BigInt operator+() const { return BigInt(*this); } BigInt operator-() const { BigInt r; r.get_mp() = -get_mp(); return r; } BigInt& operator++() { makeCopy(); ++get_mp(); return *this; } BigInt& operator--() { makeCopy(); --get_mp(); return *this; } BigInt operator++(int) { BigInt r(*this); ++(*this); return r; } BigInt operator--(int) { BigInt r(*this); --(*this); return r; } //@} /// \name Helper Functions //@{ /// Has Exact Division static bool hasExactDivision() { return false; } /// get mpz pointer (const) const Z& get_mp() const { return rep->get_mp(); } /// get mpz pointer Z& get_mp() { return rep->get_mp(); } //@} /// \name String Conversion Functions //@{ /// set value from const char* int set_str(const char* s) { makeCopy(); get_mp() = Z(s); return 0; // should be -1 if not correct in the base (we ignore) } /// convert to std::string std::string get_str() const { return get_mp().convert_to(); } //@} /// \name Conversion Functions //@{ /// intValue int intValue() const { return get_mp().convert_to(); } /// longValue long longValue() const { return get_mp().convert_to(); } /// ulongValue unsigned long ulongValue() const { return get_mp().convert_to(); } /// doubleValue double doubleValue() const { return get_mp().convert_to(); } //@} }; inline BigInt operator+(const BigInt& a, const BigInt& b) { BigInt r; r.get_mp() = a.get_mp() + b.get_mp(); return r; } inline BigInt operator-(const BigInt& a, const BigInt& b) { BigInt r; r.get_mp() = a.get_mp() - b.get_mp(); return r; } inline BigInt operator*(const BigInt& a, const BigInt& b) { BigInt r; r.get_mp() = a.get_mp() * b.get_mp(); return r; } inline BigInt operator/(const BigInt& a, const BigInt& b) { BigInt r; r.get_mp() = a.get_mp() / b.get_mp(); return r; } inline BigInt operator%(const BigInt& a, const BigInt& b) { BigInt r; r.get_mp() = a.get_mp() % b.get_mp(); return r; } inline BigInt operator&(const BigInt& a, const BigInt& b) { BigInt r; r.get_mp() = a.get_mp() & b.get_mp(); return r; } inline BigInt operator|(const BigInt& a, const BigInt& b) { BigInt r; r.get_mp() = a.get_mp()| b.get_mp(); return r; } inline BigInt operator^(const BigInt& a, const BigInt& b) { BigInt r; r.get_mp() = a.get_mp() ^ b.get_mp(); return r; } inline BigInt operator<<(const BigInt& a, unsigned long ul) { BigInt r; r.get_mp() = a.get_mp() << ul; return r; } inline BigInt operator>>(const BigInt& a, unsigned long ul) { BigInt r; r.get_mp() = a.get_mp() >> ul; return r; } inline int cmp(const BigInt& x, const BigInt& y) { return x.get_mp().compare(y.get_mp()); } inline bool operator==(const BigInt& a, const BigInt& b) { return cmp(a, b) == 0; } inline bool operator!=(const BigInt& a, const BigInt& b) { return cmp(a, b) != 0; } inline bool operator>=(const BigInt& a, const BigInt& b) { return cmp(a, b) >= 0; } inline bool operator>(const BigInt& a, const BigInt& b) { return cmp(a, b) > 0; } inline bool operator<=(const BigInt& a, const BigInt& b) { return cmp(a, b) <= 0; } inline bool operator<(const BigInt& a, const BigInt& b) { return cmp(a, b) < 0; } inline std::ostream& operator<<(std::ostream& o, const BigInt& x) { return o <>(std::istream& i, BigInt& x) { x.makeCopy(); return i >> x.get_mp(); } /// sign inline int sign(const BigInt& a) { return sign(a.get_mp()); } /// abs inline BigInt abs(const BigInt& a) { BigInt r; r.get_mp() = abs(a.get_mp()); return r; } /// neg inline BigInt neg(const BigInt& a) { BigInt r; r.get_mp() = - a.get_mp(); return r; } /// negate inline void negate(BigInt& a) { a.makeCopy(); a.get_mp() = - a.get_mp(); } /// cmpabs inline int cmpabs(const BigInt& a, const BigInt& b) { return cmp(abs(a), abs(b)); return 0; } /// \name Conversion Functions //@{ /// longValue inline long longValue(const BigInt& a) { return a.longValue(); } /// ulongValue inline unsigned long ulongValue(const BigInt& a) { assert(a >= BigInt(0)); return a.ulongValue(); } /// doubleValue inline double doubleValue(const BigInt& a) { return a.doubleValue(); } //@} /* /// \name File I/O Functions //@{ /// read from file void readFromFile(BigInt& z, std::istream& in, long maxLength = 0); /// write to file void writeToFile(const BigInt& z, std::ostream& in, int charsPerLine=80); //@} */ /// \name Misc Functions //@{ /// isEven inline bool isEven(const BigInt& z) { return bit_test(z.get_mp(),0) == 0; } /// isOdd inline bool isOdd(const BigInt& z) { return bit_test(z.get_mp(),0) == 1; } /// get exponent of power 2 inline unsigned long getBinExpo(const BigInt& z) { if (z.get_mp().is_zero()) { return (std::numeric_limits::max)(); } return lsb(abs(z.get_mp())); } /// get exponent of power k inline void getKaryExpo(const BigInt& z, BigInt& m, int& e, unsigned long uk) { BigInt k(uk), q, r; e = 0; m = z; m.makeCopy(); for(;;) { divide_qr(m.get_mp(), k.get_mp(), q.get_mp(), r.get_mp()); if (!r.get_mp().is_zero()) break; m.get_mp() = q.get_mp(); ++e; } } /// divisible(x,y) = "x | y" inline bool isDivisible(const BigInt& x, const BigInt& y) { BigInt q, r; divide_qr(x.get_mp(), y.get_mp(), q.get_mp(), r.get_mp()); return r.get_mp().is_zero(); } inline bool isDivisible(int x, int y) { return x % y == 0; } inline bool isDivisible(long x, long y) { return x % y == 0; } /// exact div inline void divexact(BigInt& z, const BigInt& x, const BigInt& y) { z.makeCopy(); BigInt r; divide_qr(x.get_mp(), y.get_mp(), z.get_mp(), r.get_mp() ); // was void mpz_divexact (mpz_t q, const mpz_t n, const mpz_t d) Is this faster? assert(r.get_mp().is_zero()); } // Chee (1/12/2004) The definition of div_exact(x,y) next // ensure that in Polynomials works with both NT=BigInt and NT=int: inline BigInt div_exact(const BigInt& x, const BigInt& y) { BigInt z; // precodition: isDivisible(x,y) divexact(z, x, y); // z is set to x/y; return z; } inline int div_exact(int x, int y) { return x/y; // precondition: isDivisible(x,y) } inline long div_exact(long x, long y) { return x/y; // precondition: isDivisible(x,y) } /// gcd inline BigInt gcd(const BigInt& a, const BigInt& b) { BigInt r; r.get_mp() = gcd(a.get_mp(), b.get_mp()); return r; } /// div_rem inline void div_rem(BigInt& q, BigInt& r, const BigInt& a, const BigInt& b) { q.makeCopy(); r.makeCopy(); divide_qr(a.get_mp(), b.get_mp(), q.get_mp(), r.get_mp()); } /// power inline void power(BigInt& c, const BigInt& a, unsigned long ul) { c.makeCopy(); //c.get_mp() = pow(a.get_mp(), ul); } // pow inline BigInt pow(const BigInt& a, unsigned long ui) { BigInt r; power(r, a, ui); return r; } // bit length inline int bitLength(const BigInt& a) { if (a.get_mp().is_zero()) { return 0; } return msb(abs(a.get_mp()))+1; } /// floorLg -- floor of log_2(a) /** Convention: a=0, floorLg(a) returns -1. * This makes sense for integer a. */ inline long floorLg(const BigInt& a) { return (sign(a) == 0) ? (-1) : (bitLength(a)-1); } /// ceilLg -- ceiling of log_2(a) where a=BigInt, int or long /** Convention: a=0, ceilLg(a) returns -1. * This makes sense for integer a. */ inline long ceilLg(const BigInt& a) { if (sign(a) == 0) return -1; unsigned long len = bitLength(a); return (lsb(abs(a.get_mp())) == len - 1) ? (len - 1) : len; } inline long ceilLg(long a) { // need this for Polynomial return ceilLg(BigInt(a)); } inline long ceilLg(int a) { // need this for Polynomial return ceilLg(BigInt(a)); } //@} } //namespace CORE #endif #endif // _CORE_BIGINT_H_