/* ---------------------------------------------------------------------- * This file is autogenerated from the file multiprecision.hpp.in during * the cmake configuration of your project. If you need to make changes * edit the original file. * ---------------------------------------------------------------------- */ #ifndef __SOPLEX_MULTIPRECISION_HPP_ #define __SOPLEX_MULTIPRECISION_HPP_ #define SOPLEX_DEBUG #include #include #include #include "soplex/spxdefines.h" #ifdef SOPLEX_WITH_GMP #include #endif #ifdef SOPLEX_WITH_BOOST #include #ifdef SOPLEX_WITH_GMP #include namespace soplex { using namespace boost::multiprecision; using Rational = number; using Integer = number; inline void SpxLcm(Integer& result, Integer a, Integer b) { mpz_lcm(result.backend().data(), a.backend().data(), b.backend().data()); } inline void SpxGcd(Integer& result, Integer a, Integer b) { mpz_gcd(result.backend().data(), a.backend().data(), b.backend().data()); } } // namespace soplex #else #include #include namespace soplex { using namespace boost::multiprecision; using Rational = cpp_rational; using Integer = cpp_int; inline void SpxLcm(Integer& result, Integer a, Integer b) { result = boost::multiprecision::lcm(a, b); } inline void SpxGcd(Integer& result, Integer a, Integer b) { result = boost::multiprecision::gcd(a, b); } } // namespace soplex #endif namespace soplex { inline void printRational(Rational r) { std::cout << r << std::endl; } inline void printInteger(Integer r) { std::cout << r << std::endl; } inline bool isAdjacentTo(const Rational& r, const double& d) { double x = (double) r; double a; double b; Rational tmp = x; // the rational value is representable in double precision if(tmp == r) return true; // the rounded value is smaller than the rational value else if(tmp < r) { a = x; b = (double)nextafter(a, 1e100); } // the rounded value is larger than the rational value else { b = x; a = (double)nextafter(b, -1e100); } return ((a == d) || (b == d)); } inline void invert(Rational& r) { r = Rational(denominator(r), numerator(r)); } /// round up to next power of two inline void powRound(Rational& r) { Integer roundval; Integer den; Integer num; MSG_DEBUG(std::cout << "rounding " << str(r) << " to power of two" << "\n"); num = numerator(r); den = denominator(r); roundval = num / den; MSG_DEBUG(std::cout << " --> " << str(roundval) << "\n"); size_t binlog = roundval == 0 ? 1 : msb(roundval) + 1; Integer base = 2; MSG_DEBUG(std::cout << " --> 2^" << binlog << "\n"); roundval = boost::multiprecision::pow(base, (unsigned int)binlog); MSG_DEBUG(std::cout << " --> " << str(roundval) << "\n"); r = roundval; MSG_DEBUG(std::cout << " --> " << str(r) << "\n"); } /* find substring, ignore case */ static std::string::const_iterator findSubStringIC(const std::string& substr, const std::string& str) { auto it = std::search( str.begin(), str.end(), substr.begin(), substr.end(), [](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); } ); return it; } inline Rational ratFromString(const char* desc) { Rational res; if(0 == strcmp(desc, "inf")) { res = 1e100; } else if(0 == strcmp(desc, "-inf")) { res = -1e100; } else { std::string s(desc); /* case 1: string is given in nom/den format */ if(s.find('.') == std::string::npos) { if(s[0] == '+') res = Rational(desc + 1); else res = Rational(desc); } /* case 2: string is given as base-10 decimal number */ else { std::string::const_iterator it = findSubStringIC("e", s); int mult = 0; if(it != s.end()) { int exponentidx = int(it - s.begin()); mult = std::stoi(s.substr(exponentidx + 1, s.length())); s = s.substr(0, exponentidx); } // std::cout << s << std::endl; if(s[0] == '.') s.insert(0, "0"); size_t pos = s.find('.'); size_t exp = s.length() - 1 - pos; std::string den("1"); for(size_t i = 0; i < exp; ++i) den.append("0"); s.erase(pos, 1); assert(std::all_of(s.begin() + 1, s.end(), ::isdigit)); // remove padding 0s if(s[0] == '-') s.erase(1, std::min(s.substr(1).find_first_not_of('0'), s.size() - 1)); else s.erase(0, std::min(s.find_first_not_of('0'), s.size() - 1)); s.append("/"); s.append(den); res = Rational(s); res *= pow(10, mult); } } return res; } } // namespace soplex #else #ifndef SOPLEX_WITH_GMP using mpq_t = char; #endif using Integer = int; // this is a placeholder class to ensure compilation when boost ist not linked. Rationals need BOOST in order to function. class Rational { public: ///@name Construction and destruction ///@{ inline void rationalErrorMessage() const { MSG_ERROR(std::cerr << "Using rational methods without linking boost is not supported" << std::endl; ) }; /// default constructor inline Rational() { }; /// copy constructor inline Rational(const Rational& r) { }; /// constructor from long double inline Rational(const long double& r) { }; /// constructor from double inline Rational(const double& r) { }; ///constructor from int inline Rational(const int& i) { }; /// constructor from Integer inline Rational(const Integer& num, const Integer& den) { }; /// constructor from mpq_t (GMP only) inline Rational(const mpq_t& q) { }; #ifdef SOPLEX_WITH_BOOST // constructor from boost number inline template Rational(const boost::multiprecision::number& q) { }; #endif /// destructor inline ~Rational() { }; /// assignment operator inline Rational& operator=(const Rational&) { return *this; }; /// assignment operator from long double inline Rational& operator=(const long double& r) { return *this; }; /// assignment operator from double inline Rational& operator=(const double& r) { return *this; }; /// assignment operator from int inline Rational& operator=(const int& i) { return *this; }; /// assignment operator from mpq_t inline Rational& operator=(const mpq_t& q) { return *this; }; inline void assign(const Rational&) { rationalErrorMessage(); }; inline void assign(const long double& r) { rationalErrorMessage(); }; inline void assign(const double& r) { rationalErrorMessage(); }; inline void assign(const int& i) { rationalErrorMessage(); }; ///@name Typecasts ///@{ inline operator double() const { return 0; }; inline operator long double() const { return 0; }; inline operator float() const { return 0; }; #ifdef SOPLEX_WITH_BOOST #ifndef SOPLEX_WITH_CPPMPF // Operator to typecast Rational to one of the Boost Number types inline template operator boost::multiprecision::number() const { rationalErrorMessage(); return 0; }; #else // Operator to typecast Rational to one of the Boost Number types inline template operator boost::multiprecision::number, eto>() const { rationalErrorMessage(); return 0; }; #endif #endif ///@name Typecasts ///@{ ///@} ///@name Arithmetic operators ///@{ /// addition operator inline Rational operator+(const Rational& r) const { rationalErrorMessage(); return *this; } /// addition assignment operator inline Rational operator+=(const Rational& r) { rationalErrorMessage(); return *this; } /// addition operator for doubles inline Rational operator+(const double& r) const { rationalErrorMessage(); return *this; } /// addition assignment operator for doubles inline Rational operator+=(const double& r) { rationalErrorMessage(); return *this; } /// addition operator for ints inline Rational operator+(const int& r) const { rationalErrorMessage(); return *this; } /// addition assignment operator for ints inline Rational operator+=(const int& r) { rationalErrorMessage(); return *this; } /// subtraction operator inline Rational operator-(const Rational& r) const { rationalErrorMessage(); return *this; } /// subtraction assignment operator inline Rational operator-=(const Rational& r) { rationalErrorMessage(); return *this; } /// subtraction operator for doubles inline Rational operator-(const double& r) const { rationalErrorMessage(); return *this; } /// subtraction assignment operator for doubles inline Rational operator-=(const double& r) { rationalErrorMessage(); return *this; } /// subtraction operator for ints inline Rational operator-(const int& r) const { rationalErrorMessage(); return *this; } /// subtraction assignment operator for ints inline Rational operator-=(const int& r) { rationalErrorMessage(); return *this; } /// multiplication operator inline Rational operator*(const Rational& r) const { rationalErrorMessage(); return *this; } /// multiplication assignment operator operator inline Rational operator*=(const Rational& r) { rationalErrorMessage(); return *this; } /// multiplication operator for doubles inline Rational operator*(const double& r) const { rationalErrorMessage(); return *this; } /// multiplication assignment operator for doubles inline Rational operator*=(const double& r) { rationalErrorMessage(); return *this; } /// multiplication operator for ints inline Rational operator*(const int& r) const { rationalErrorMessage(); return *this; } /// multiplication assignment operator for ints inline Rational operator*=(const int& r) { rationalErrorMessage(); return *this; } /// division operator inline Rational operator/(const Rational& r) const { rationalErrorMessage(); return *this; } /// division assignment operator inline Rational operator/=(const Rational& r) { rationalErrorMessage(); return *this; } /// division operator for doubles inline Rational operator/(const double& r) const { rationalErrorMessage(); return *this; } /// division assignment operator for doubles inline Rational operator/=(const double& r) { rationalErrorMessage(); return *this; } /// division operator for ints inline Rational operator/(const int& r) const { rationalErrorMessage(); return *this; } /// division assignment operator for ints inline Rational operator/=(const int& r) { rationalErrorMessage(); return *this; } /// add product of two rationals Rational& addProduct(const Rational& r, const Rational& s) { rationalErrorMessage(); return *this; } /// subtract product of two rationals Rational& subProduct(const Rational& r, const Rational& s) { rationalErrorMessage(); return *this; } /// add quotient of two rationals, r divided by s Rational& addQuotient(const Rational& r, const Rational& s) { rationalErrorMessage(); return *this; } /// subtract quotient of two rationals, r divided by s Rational& subQuotient(const Rational& r, const Rational& s) { rationalErrorMessage(); return *this; } ///@} ///@name Methods for checking exactness of doubles ///@{ /// checks if \p d is exactly equal to the Rational and if not, if it is one of the two adjacent doubles inline bool isAdjacentTo(const double& d) const { rationalErrorMessage(); return false; }; ///@} ///@name Methods for querying size ///@{ /// Size in specified base (bit size for base 2) int sizeInBase(const int base = 2) const { rationalErrorMessage(); return 0; }; ///@} ///@name Conversion from and to String ///@{ inline friend std::ostream& operator<<(std::ostream& os, const Rational& r) { r.rationalErrorMessage(); return os; }; inline std::string str() const { this->rationalErrorMessage(); return std::string(""); }; ///@} ///@name Friends ///@{ inline friend int compareRational(const Rational& r, const Rational& s) { r.rationalErrorMessage(); return 0; }; inline friend bool operator!=(const Rational& r, const Rational& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator==(const Rational& r, const Rational& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator<(const Rational& r, const Rational& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator<=(const Rational& r, const Rational& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator>(const Rational& r, const Rational& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator>=(const Rational& r, const Rational& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator!=(const Rational& r, const double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator==(const Rational& r, const double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator<(const Rational& r, const double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator<=(const Rational& r, const double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator>(const Rational& r, const double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator>=(const Rational& r, const double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator!=(const double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator==(const double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator<(const double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator<=(const double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator>(const double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator>=(const double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator!=(const Rational& r, const long double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator==(const Rational& r, const long double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator<(const Rational& r, const long double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator<=(const Rational& r, const long double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator>(const Rational& r, const long double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator>=(const Rational& r, const long double& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator!=(const long double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator==(const long double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator<(const long double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator<=(const long double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator>(const long double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator>=(const long double& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator!=(const Rational& r, const float& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator==(const Rational& r, const float& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator<(const Rational& r, const float& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator<=(const Rational& r, const float& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator>(const Rational& r, const float& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator>=(const Rational& r, const float& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator!=(const float& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator==(const float& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator<(const float& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator<=(const float& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator>(const float& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator>=(const float& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend Rational operator+(const double& d, const Rational& r) { r.rationalErrorMessage(); return r; }; inline friend Rational operator-(const double& d, const Rational& r) { r.rationalErrorMessage(); return r; }; inline friend Rational operator*(const double& d, const Rational& r) { r.rationalErrorMessage(); return r; }; inline friend Rational operator/(const double& d, const Rational& r) { r.rationalErrorMessage(); return r; }; inline friend bool operator!=(const Rational& r, const int& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator==(const Rational& r, const int& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator<(const Rational& r, const int& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator<=(const Rational& r, const int& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator>(const Rational& r, const int& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator>=(const Rational& r, const int& s) { r.rationalErrorMessage(); return false; }; inline friend bool operator!=(const int& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator==(const int& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator<(const int& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator<=(const int& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator>(const int& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend bool operator>=(const int& r, const Rational& s) { s.rationalErrorMessage(); return false; }; inline friend Rational operator+(const int& d, const Rational& r) { r.rationalErrorMessage(); return r; }; inline friend Rational operator-(const int& d, const Rational& r) { r.rationalErrorMessage(); return r; }; inline friend Rational operator*(const int& d, const Rational& r) { r.rationalErrorMessage(); return r; }; inline friend Rational operator/(const int& d, const Rational& r) { r.rationalErrorMessage(); return r; }; inline friend Rational spxAbs(const Rational& r) { r.rationalErrorMessage(); return r; }; inline friend int sign(const Rational& r) { r.rationalErrorMessage(); return 0; }; inline friend Rational operator-(const Rational& q) { q.rationalErrorMessage(); return q; };///@name Construction and destruction ///@{ }; inline Integer numerator(const Rational& r) { r.rationalErrorMessage(); return 0; } inline Integer denominator(const Rational& r) { r.rationalErrorMessage(); return 0; } inline Rational ratFromString(const char* desc) { return Rational(); } inline void SpxLcm(Integer& result, Integer a, Integer b) {} inline void SpxGcd(Integer& result, Integer a, Integer b) {} inline void divide_qr(Integer& result, Integer& result2, Integer a, Integer b) {} inline void invert(Rational& r) { r.rationalErrorMessage(); } inline void powRound(Rational& r) { r.rationalErrorMessage(); } #endif namespace soplex { /// Size in specified base (bit size for base 2) inline int sizeInBase(const Rational R, const int base) { #ifndef SOPLEX_WITH_BOOST MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) return 0; #else if(R == Rational(0)) return 3; Integer num = numerator(R); Integer den = denominator(R); size_t numsize, densize; #ifdef SOPLEX_WITH_GMP densize = mpz_sizeinbase(den.backend().data(), base); numsize = mpz_sizeinbase(num.backend().data(), base); #else if(base != 2) { densize = (size_t)(log2(den.convert_to()) / log2(double(base))) + 1; numsize = (size_t)(log2(num.convert_to()) / log2(double(base))) + 1; } else { densize = msb(den) + 1; numsize = msb(num) + 1; } #endif return (int)(densize + numsize); #endif } /// Total size of rational vector. inline int totalSizeRational(const Rational* vector, const int length, const int base) { assert(vector != 0); assert(length >= 0); assert(base >= 0); int size = 0; for(int i = 0; i < length; i++) size += sizeInBase(vector[i], base); return size; } /// Size of least common multiple of denominators in rational vector. inline int dlcmSizeRational(const Rational* vector, const int length, const int base) { assert(vector != 0); assert(length >= 0); #ifndef SOPLEX_WITH_BOOST MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) return 0; #else Integer lcm = 1; for(int i = 0; i < length; i++) SpxLcm(lcm, lcm, denominator(vector[i])); int size = sizeInBase(Rational(lcm), base) + 1; return size; #endif } /// Size of largest denominator in rational vector. inline int dmaxSizeRational(const Rational* vector, const int length, const int base) { assert(vector != 0); assert(length >= 0); #ifndef SOPLEX_WITH_BOOST MSG_ERROR(std::cerr << "ERROR: rational solve without Boost not defined!" << std::endl;) return 0; #else size_t dmax = 0; for(int i = 0; i < length; i++) { size_t dsize = sizeInBase(Rational(denominator(vector[i])), base) + 1; if(dsize > dmax) dmax = dsize; } return (int)dmax; #endif } } // namespace soplex #endif //}