#ifndef __SOPLEX_MULTIPRECISION_HPP_
#define __SOPLEX_MULTIPRECISION_HPP_
#define SOPLEX_DEBUG
#include <numeric>
#include <vector>
#include <string>
#include "soplex/spxdefines.h"
#ifdef SOPLEX_WITH_GMP
#include <gmp.h>
#endif
#ifdef SOPLEX_WITH_BOOST
#include <boost/multiprecision/number.hpp>
#ifdef SOPLEX_WITH_GMP
#include <boost/multiprecision/gmp.hpp>
namespace soplex
{
using namespace boost::multiprecision;
using Rational = number<gmp_rational, et_off>;
using Integer = number<gmp_int, et_off>;
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());
}
} #else
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/detail/default_ops.hpp>
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);
}
} #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;
if(tmp == r)
return true;
else if(tmp < r)
{
a = x;
b = (double)nextafter(a, 1e100);
}
else
{
b = x;
a = (double)nextafter(b, -1e100);
}
return ((a == d) || (b == d));
}
inline void invert(Rational& r)
{
r = Rational(denominator(r), numerator(r));
}
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");
}
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);
if(s.find('.') == std::string::npos)
{
if(s[0] == '+')
res = Rational(desc + 1);
else
res = Rational(desc);
}
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);
}
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));
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;
}
} #else
#ifndef SOPLEX_WITH_GMP
using mpq_t = char;
#endif
using Integer = int;
class Rational
{
public:
inline void rationalErrorMessage() const
{
MSG_ERROR(std::cerr << "Using rational methods without linking boost is not supported" << std::endl;
)
};
inline Rational()
{
};
inline Rational(const Rational& r)
{
};
inline Rational(const long double& r)
{
};
inline Rational(const double& r)
{
};
inline Rational(const int& i)
{
};
inline Rational(const Integer& num, const Integer& den)
{
};
inline Rational(const mpq_t& q)
{
};
#ifdef SOPLEX_WITH_BOOST
inline template <typename T, boost::multiprecision::expression_template_option eto>
Rational(const boost::multiprecision::number<T, eto>& q)
{
};
#endif
inline ~Rational()
{
};
inline Rational& operator=(const Rational&)
{
return *this;
};
inline Rational& operator=(const long double& r)
{
return *this;
};
inline Rational& operator=(const double& r)
{
return *this;
};
inline Rational& operator=(const int& i)
{
return *this;
};
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();
};
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
inline template <typename T, boost::multiprecision::expression_template_option eto>
operator boost::multiprecision::number<T, eto>() const
{
rationalErrorMessage();
return 0;
};
#else
inline template <unsigned bits, boost::multiprecision::expression_template_option eto>
operator boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<bits>, eto>()
const
{
rationalErrorMessage();
return 0;
};
#endif
#endif
inline Rational operator+(const Rational& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator+=(const Rational& r)
{
rationalErrorMessage();
return *this;
}
inline Rational operator+(const double& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator+=(const double& r)
{
rationalErrorMessage();
return *this;
}
inline Rational operator+(const int& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator+=(const int& r)
{
rationalErrorMessage();
return *this;
}
inline Rational operator-(const Rational& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator-=(const Rational& r)
{
rationalErrorMessage();
return *this;
}
inline Rational operator-(const double& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator-=(const double& r)
{
rationalErrorMessage();
return *this;
}
inline Rational operator-(const int& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator-=(const int& r)
{
rationalErrorMessage();
return *this;
}
inline Rational operator*(const Rational& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator*=(const Rational& r)
{
rationalErrorMessage();
return *this;
}
inline Rational operator*(const double& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator*=(const double& r)
{
rationalErrorMessage();
return *this;
}
inline Rational operator*(const int& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator*=(const int& r)
{
rationalErrorMessage();
return *this;
}
inline Rational operator/(const Rational& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator/=(const Rational& r)
{
rationalErrorMessage();
return *this;
}
inline Rational operator/(const double& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator/=(const double& r)
{
rationalErrorMessage();
return *this;
}
inline Rational operator/(const int& r) const
{
rationalErrorMessage();
return *this;
}
inline Rational operator/=(const int& r)
{
rationalErrorMessage();
return *this;
}
Rational& addProduct(const Rational& r, const Rational& s)
{
rationalErrorMessage();
return *this;
}
Rational& subProduct(const Rational& r, const Rational& s)
{
rationalErrorMessage();
return *this;
}
Rational& addQuotient(const Rational& r, const Rational& s)
{
rationalErrorMessage();
return *this;
}
Rational& subQuotient(const Rational& r, const Rational& s)
{
rationalErrorMessage();
return *this;
}
inline bool isAdjacentTo(const double& d) const
{
rationalErrorMessage();
return false;
};
int sizeInBase(const int base = 2) const
{
rationalErrorMessage();
return 0;
};
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("");
};
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;
}; };
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
{
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<double>()) / log2(double(base))) + 1;
numsize = (size_t)(log2(num.convert_to<double>()) / log2(double(base))) + 1;
}
else
{
densize = msb(den) + 1;
numsize = msb(num) + 1;
}
#endif
return (int)(densize + numsize);
#endif
}
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;
}
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
}
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
}
} #endif