25struct std::hash<mpq_class> {
26 size_t operator()(
const mpq_class &val)
const noexcept;
31std::strong_ordering operator<=>(
const mpq_class &lhs,
const mpq_t &rhs);
32std::strong_ordering operator<=>(
const mpq_t &lhs,
const mpq_class &rhs);
36inline const mpq_class infinity{mpz_class{0}, 0};
38inline std::size_t complexity(
const mpq_class &val) {
39 return mpz_size(val.get_num().get_mpz_t()) + mpz_size(val.get_den().get_mpz_t());
49std::vector<mpq_class> ToMpqVector(
const mpq_t *x,
int size);
56mpz_class floor(
const mpq_class &val);
62mpz_class ceil(
const mpq_class &val);
69inline bool sign(
const mpq_class &val) {
return val.get_num() >= 0; }
77inline bool IsInfinity(
const mpq_class &val) {
return mpz_sgn(val.get_den().get_mpz_t()) == 0; }
106inline const mpq_t &ToMpq(
const mpq_class &cla) {
return *
reinterpret_cast<const mpq_t *
>(cla.get_mpq_t()); }
108inline mpq_t &ToMpq(mpq_class &cla) {
return *
reinterpret_cast<mpq_t *
>(cla.get_mpq_t()); }
117inline const mpq_class &ToMpqClass(
const mpq_t &mpq) {
return reinterpret_cast<const mpq_class &
>(mpq); }
127inline mpq_class &ToMpqClass(mpq_t &mpq) {
return reinterpret_cast<mpq_class &
>(mpq); }
135inline bool IsDigitOrSign(
const char c) {
return std::isdigit(c) || c ==
'+' || c ==
'-'; }
169inline mpq_class StringToMpq(std::string_view input) {
170 if (input.empty())
return mpq_class{0};
172 const bool is_negative = input[0] ==
'-';
173 if (is_negative || input[0] ==
'+') input.remove_prefix(1);
174 if (input ==
"inf")
return {is_negative ? -1e100 : 1e100};
176 constexpr std::size_t max_size = 1 << 10;
177 char str_buffer[max_size + 1];
179 const std::size_t buffer_size = std::min(input.size(), max_size);
180 std::memcpy(str_buffer, input.data(), buffer_size);
181 str_buffer[buffer_size] =
'\0';
182 std::string_view str{str_buffer, buffer_size};
185 const size_t symbol_pos = str.find_first_of(
"/.Ee");
186 if (symbol_pos == std::string::npos) {
187 const size_t start_pos = str.find_first_not_of(
'0');
188 if (start_pos == std::string_view::npos)
return {0};
189 str.remove_prefix(start_pos);
190 return is_negative ? -mpq_class{str.data()} : mpq_class{str.data()};
194 if (str[symbol_pos] ==
'/') {
195 mpq_class res{str.data()};
197 return is_negative ? -res : res;
200 const size_t e_pos = str[symbol_pos] ==
'e' || str[symbol_pos] ==
'E' ? symbol_pos : str.find_first_of(
"Ee");
201 mpz_class mult{is_negative ? -1 : 1};
202 bool is_exp_positive =
true;
205 if (e_pos != std::string::npos) {
206 const long exponent = std::stol(str.data() + e_pos + 1);
207 is_exp_positive = exponent >= 0;
209 mpz_pow_ui(mult.get_mpz_t(), mult.get_mpz_t(), std::abs(exponent));
210 if (is_negative) mult = -mult;
212 str = str.substr(0, e_pos);
214 if (str.empty())
return is_exp_positive ? mpq_class{mult} : is_negative ? mpq_class{-1, -mult} : mpq_class{1, mult};
217 const size_t len = str.length();
220 if (str[symbol_pos] ==
'e' || str[symbol_pos] ==
'E') {
221 str_buffer[len] =
'\0';
222 const mpq_class res{str.data(), 10};
223 return is_exp_positive ? mpq_class{res * mult} : mpq_class{res / mult};
226 const size_t &dot_pos = symbol_pos;
229 size_t start_pos = str.find_first_not_of(
'0');
233 if (start_pos == dot_pos) {
234 start_pos = str.find_first_not_of(
'0', dot_pos + 1);
236 if (start_pos == std::string_view::npos) {
239 digits = len - start_pos;
242 digits = len - start_pos - 1;
245 const size_t n_decimals = len - dot_pos - 1;
246 char str_number[max_size * 2 + 4];
248 if (digits > n_decimals) {
249 memcpy(str_number, str.data() + start_pos, digits - n_decimals);
250 memcpy(str_number + dot_pos, str.data() + dot_pos + 1, n_decimals);
252 memcpy(str_number, str.data() + start_pos, n_decimals);
255 str_number[digits] =
'/';
256 str_number[digits + 1] =
'1';
257 memset(str_number + digits + 2,
'0', n_decimals);
258 str_number[digits + 2 + n_decimals] =
'\0';
260 mpq_class res{str_number, 10};
262 return is_exp_positive ? mpq_class{res * mult} : res / mult;
269#ifdef DELPI_INCLUDE_FMT
271#include "delpi/util/logging.h"
273OSTREAM_FORMATTER(mpq_class)
Global namespace for the delpi library.
size_t operator()(const mpq_class &val) const noexcept
Hash a gmp rational.