File indexing completed on 2025-01-18 09:42:31
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_MP_GMP_HPP
0008 #define BOOST_MP_GMP_HPP
0009
0010 #include <boost/multiprecision/detail/standalone_config.hpp>
0011 #include <boost/multiprecision/number.hpp>
0012 #include <boost/multiprecision/debug_adaptor.hpp>
0013 #include <boost/multiprecision/detail/integer_ops.hpp>
0014 #include <boost/multiprecision/detail/float128_functions.hpp>
0015 #include <boost/multiprecision/detail/digits.hpp>
0016 #include <boost/multiprecision/detail/atomic.hpp>
0017 #include <boost/multiprecision/detail/hash.hpp>
0018 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
0019 #include <boost/multiprecision/detail/assert.hpp>
0020 #include <boost/multiprecision/detail/fpclassify.hpp>
0021 #include <boost/multiprecision/detail/string_helpers.hpp>
0022 #include <algorithm>
0023 #include <cctype>
0024 #include <cfloat>
0025 #include <climits>
0026 #include <clocale>
0027 #include <cmath>
0028 #include <cstdint>
0029 #include <cstdlib>
0030 #include <cstring>
0031 #include <iomanip>
0032 #include <iostream>
0033 #include <limits>
0034 #include <memory>
0035 #include <type_traits>
0036 #include <utility>
0037
0038
0039
0040
0041 #ifdef BOOST_MP_MATH_AVAILABLE
0042 #include <boost/math/special_functions/asinh.hpp>
0043 #include <boost/math/special_functions/acosh.hpp>
0044 #include <boost/math/special_functions/atanh.hpp>
0045 #include <boost/math/special_functions/cbrt.hpp>
0046 #include <boost/math/special_functions/expm1.hpp>
0047 #include <boost/math/special_functions/gamma.hpp>
0048 #endif
0049
0050 #ifdef BOOST_MSVC
0051 #pragma warning(push)
0052 #pragma warning(disable : 4127)
0053 #endif
0054 #include <gmp.h>
0055 #ifdef BOOST_MSVC
0056 #pragma warning(pop)
0057 #endif
0058
0059 #if defined(__MPIR_VERSION) && defined(__MPIR_VERSION_MINOR) && defined(__MPIR_VERSION_PATCHLEVEL)
0060 #define BOOST_MP_MPIR_VERSION (__MPIR_VERSION * 10000 + __MPIR_VERSION_MINOR * 100 + __MPIR_VERSION_PATCHLEVEL)
0061 #else
0062 #define BOOST_MP_MPIR_VERSION 0
0063 #endif
0064
0065 namespace boost {
0066 namespace multiprecision {
0067 namespace backends {
0068
0069 #ifdef BOOST_MSVC
0070
0071 #pragma warning(push)
0072
0073 #endif
0074
0075 template <unsigned digits10>
0076 struct gmp_float;
0077 struct gmp_int;
0078 struct gmp_rational;
0079
0080 }
0081
0082 template <>
0083 struct number_category<backends::gmp_int> : public std::integral_constant<int, number_kind_integer>
0084 {};
0085 template <>
0086 struct number_category<backends::gmp_rational> : public std::integral_constant<int, number_kind_rational>
0087 {};
0088 template <unsigned digits10>
0089 struct number_category<backends::gmp_float<digits10> > : public std::integral_constant<int, number_kind_floating_point>
0090 {};
0091
0092 namespace backends {
0093
0094
0095
0096
0097
0098 namespace detail {
0099
0100 template <unsigned digits10>
0101 struct gmp_float_imp
0102 {
0103 #ifdef BOOST_HAS_LONG_LONG
0104 using signed_types = std::tuple<long, long long> ;
0105 using unsigned_types = std::tuple<unsigned long, unsigned long long>;
0106 #else
0107 using signed_types = std::tuple<long> ;
0108 using unsigned_types = std::tuple<unsigned long>;
0109 #endif
0110 using float_types = std::tuple<double, long double>;
0111 using exponent_type = long ;
0112
0113 gmp_float_imp() noexcept
0114 {
0115 m_data[0]._mp_d = nullptr;
0116 m_data[0]._mp_prec = 1;
0117 }
0118
0119 gmp_float_imp(const gmp_float_imp& o)
0120 {
0121
0122
0123
0124
0125
0126
0127 mpf_init2(m_data, preserve_source_precision() ? mpf_get_prec(o.data()) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
0128 if (o.m_data[0]._mp_d)
0129 mpf_set(m_data, o.m_data);
0130 }
0131
0132 gmp_float_imp(gmp_float_imp&& o) noexcept
0133 {
0134 if ((this->get_default_options() == variable_precision_options::preserve_target_precision) && (mpf_get_prec(o.data()) != boost::multiprecision::detail::digits10_2_2(get_default_precision())))
0135 {
0136 mpf_init2(m_data, boost::multiprecision::detail::digits10_2_2(get_default_precision()));
0137 *this = static_cast<const gmp_float_imp&>(o);
0138 }
0139 else
0140 {
0141 m_data[0] = o.m_data[0];
0142 o.m_data[0]._mp_d = nullptr;
0143 }
0144 }
0145
0146 gmp_float_imp& operator=(const gmp_float_imp& o)
0147 {
0148 if (m_data[0]._mp_d == nullptr)
0149 {
0150 mpf_init2(m_data, preserve_source_precision() ? mpf_get_prec(o.data()) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
0151 mpf_set(m_data, o.m_data);
0152 }
0153 else if (preserve_source_precision() && (mpf_get_prec(data()) != mpf_get_prec(o.data())))
0154 {
0155 mpf_t t;
0156 mpf_init2(t, mpf_get_prec(o.data()));
0157 mpf_set(t, o.data());
0158 mpf_swap(data(), t);
0159 mpf_clear(t);
0160 }
0161 else
0162 {
0163 mpf_set(m_data, o.m_data);
0164 }
0165 return *this;
0166 }
0167
0168 gmp_float_imp& operator=(gmp_float_imp&& o) noexcept
0169 {
0170 if ((this->get_default_options() == variable_precision_options::preserve_target_precision) && (mpf_get_prec(o.data()) != mpf_get_prec(data())))
0171 *this = static_cast<const gmp_float_imp&>(o);
0172 else
0173 {
0174 mpf_swap(m_data, o.m_data);
0175 }
0176 return *this;
0177 }
0178
0179 #ifdef BOOST_HAS_LONG_LONG
0180 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
0181 gmp_float_imp& operator=(unsigned long long i)
0182 {
0183 *this = static_cast<unsigned long>(i);
0184 return *this;
0185 }
0186 #else
0187 gmp_float_imp& operator=(unsigned long long i)
0188 {
0189 if (m_data[0]._mp_d == nullptr)
0190 {
0191 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0192 }
0193 unsigned long long mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
0194 unsigned shift = 0;
0195 mpf_t t;
0196 mpf_init2(t, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0197 mpf_set_ui(m_data, 0);
0198 while (i)
0199 {
0200 mpf_set_ui(t, static_cast<unsigned long>(i & mask));
0201 if (shift)
0202 mpf_mul_2exp(t, t, shift);
0203 mpf_add(m_data, m_data, t);
0204 shift += std::numeric_limits<unsigned long>::digits;
0205 i >>= std::numeric_limits<unsigned long>::digits;
0206 }
0207 mpf_clear(t);
0208 return *this;
0209 }
0210 #endif
0211 gmp_float_imp& operator=(long long i)
0212 {
0213 if (m_data[0]._mp_d == nullptr)
0214 {
0215 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0216 }
0217 bool neg = i < 0;
0218 *this = static_cast<unsigned long long>(boost::multiprecision::detail::unsigned_abs(i));
0219 if (neg)
0220 mpf_neg(m_data, m_data);
0221 return *this;
0222 }
0223 #endif
0224 gmp_float_imp& operator=(unsigned long i)
0225 {
0226 if (m_data[0]._mp_d == nullptr)
0227 {
0228 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0229 }
0230 mpf_set_ui(m_data, i);
0231 return *this;
0232 }
0233 gmp_float_imp& operator=(long i)
0234 {
0235 if (m_data[0]._mp_d == nullptr)
0236 {
0237 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0238 }
0239 mpf_set_si(m_data, i);
0240 return *this;
0241 }
0242 #ifdef BOOST_HAS_INT128
0243 gmp_float_imp& operator=(uint128_type i)
0244 {
0245 if (m_data[0]._mp_d == nullptr)
0246 {
0247 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0248 }
0249 unsigned long mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
0250 unsigned shift = 0;
0251 mpf_t t;
0252 mpf_init2(t, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0253 mpf_set_ui(m_data, 0);
0254 while (i)
0255 {
0256 mpf_set_ui(t, static_cast<unsigned long>(i & mask));
0257 if (shift)
0258 mpf_mul_2exp(t, t, shift);
0259 mpf_add(m_data, m_data, t);
0260 shift += std::numeric_limits<unsigned long>::digits;
0261 i >>= std::numeric_limits<unsigned long>::digits;
0262 }
0263 mpf_clear(t);
0264 return *this;
0265 }
0266 gmp_float_imp& operator=(int128_type i)
0267 {
0268 if (m_data[0]._mp_d == nullptr)
0269 {
0270 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0271 }
0272 bool neg = i < 0;
0273 *this = static_cast<uint128_type>(boost::multiprecision::detail::unsigned_abs(i));
0274 if (neg)
0275 mpf_neg(m_data, m_data);
0276 return *this;
0277 }
0278 #endif
0279 gmp_float_imp& operator=(double d)
0280 {
0281 if (m_data[0]._mp_d == nullptr)
0282 {
0283 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0284 }
0285 mpf_set_d(m_data, d);
0286 return *this;
0287 }
0288 template <class F>
0289 gmp_float_imp& assign_float(F a)
0290 {
0291 BOOST_MP_FLOAT128_USING using std::floor; using std::frexp; using std::ldexp;
0292
0293 if (m_data[0]._mp_d == nullptr)
0294 {
0295 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0296 }
0297
0298 if (a == 0)
0299 {
0300 mpf_set_si(m_data, 0);
0301 return *this;
0302 }
0303
0304 if (a == 1)
0305 {
0306 mpf_set_si(m_data, 1);
0307 return *this;
0308 }
0309
0310 BOOST_MP_ASSERT(!BOOST_MP_ISINF(a));
0311 BOOST_MP_ASSERT(!BOOST_MP_ISNAN(a));
0312
0313 int e;
0314 F f, term;
0315 mpf_set_ui(m_data, 0u);
0316
0317 f = frexp(a, &e);
0318
0319 constexpr int shift = std::numeric_limits<int>::digits - 1;
0320
0321 while (f)
0322 {
0323
0324 f = ldexp(f, shift);
0325 term = floor(f);
0326 e -= shift;
0327 mpf_mul_2exp(m_data, m_data, shift);
0328 if (term > 0)
0329 mpf_add_ui(m_data, m_data, static_cast<unsigned>(term));
0330 else
0331 mpf_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
0332 f -= term;
0333 }
0334 if (e > 0)
0335 mpf_mul_2exp(m_data, m_data, e);
0336 else if (e < 0)
0337 mpf_div_2exp(m_data, m_data, -e);
0338 return *this;
0339 }
0340 gmp_float_imp& operator=(long double a)
0341 {
0342 return assign_float(a);
0343 }
0344 #ifdef BOOST_HAS_FLOAT128
0345 gmp_float_imp& operator= (float128_type a)
0346 {
0347 return assign_float(a);
0348 }
0349 #endif
0350 gmp_float_imp& operator=(const char* s)
0351 {
0352 if (m_data[0]._mp_d == nullptr)
0353 {
0354 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
0355 }
0356 if (s && (*s == '+'))
0357 ++s;
0358
0359
0360
0361 static const char* digits = "0123456789";
0362 const char* p = s;
0363 if (*s == '-')
0364 ++s;
0365 s += boost::multiprecision::detail::find_first_not_of(s, s + std::strlen(s), digits);
0366 std::lconv const* l = std::localeconv();
0367 std::size_t len = strlen(l->decimal_point);
0368 if (std::find(l->decimal_point, l->decimal_point + len, *s) != l->decimal_point + len)
0369 {
0370 ++s;
0371 s += boost::multiprecision::detail::find_first_not_of(s, s + std::strlen(s), digits);
0372 }
0373 if ((*s == 'e') || (*s == 'E'))
0374 {
0375 ++s;
0376 if ((*s == '+') || (*s == '-'))
0377 ++s;
0378 s += boost::multiprecision::detail::find_first_not_of(s, s + std::strlen(s), digits);
0379 }
0380 if(*s)
0381 BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid floating point number.")));
0382
0383 s = p;
0384
0385 if (0 != mpf_set_str(m_data, s, 10))
0386 BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid floating point number.")));
0387 return *this;
0388 }
0389 void swap(gmp_float_imp& o) noexcept
0390 {
0391 mpf_swap(m_data, o.m_data);
0392 }
0393 std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
0394 {
0395 BOOST_MP_ASSERT(m_data[0]._mp_d);
0396
0397 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
0398 bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
0399 std::streamsize org_digits(digits);
0400
0401 if (scientific && digits)
0402 ++digits;
0403
0404 std::string result;
0405 mp_exp_t e;
0406 void* (*alloc_func_ptr)(size_t);
0407 void* (*realloc_func_ptr)(void*, size_t, size_t);
0408 void (*free_func_ptr)(void*, size_t);
0409 mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
0410
0411 if (mpf_sgn(m_data) == 0)
0412 {
0413 e = 0;
0414 result = "0";
0415 if (fixed && digits)
0416 ++digits;
0417 }
0418 else
0419 {
0420 char* ps = mpf_get_str(nullptr, &e, 10, static_cast<std::size_t>(digits), m_data);
0421 --e;
0422 if (fixed)
0423 {
0424
0425 (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
0426 digits += e + 1;
0427 if (digits == 0)
0428 {
0429
0430
0431 ps = mpf_get_str(nullptr, &e, 10, 0, m_data);
0432 --e;
0433 unsigned offset = *ps == '-' ? 1 : 0;
0434 if (ps[offset] > '5')
0435 {
0436 ++e;
0437 ps[offset] = '1';
0438 ps[offset + 1] = 0;
0439 }
0440 else if (ps[offset] == '5')
0441 {
0442 unsigned i = offset + 1;
0443 bool round_up = false;
0444 while (ps[i] != 0)
0445 {
0446 if (ps[i] != '0')
0447 {
0448 round_up = true;
0449 break;
0450 }
0451 ++i;
0452 }
0453 if (round_up)
0454 {
0455 ++e;
0456 ps[offset] = '1';
0457 ps[offset + 1] = 0;
0458 }
0459 else
0460 {
0461 ps[offset] = '0';
0462 ps[offset + 1] = 0;
0463 }
0464 }
0465 else
0466 {
0467 ps[offset] = '0';
0468 ps[offset + 1] = 0;
0469 }
0470 }
0471 else if (digits > 0)
0472 {
0473 mp_exp_t old_e = e;
0474 ps = mpf_get_str(nullptr, &e, 10, static_cast<std::size_t>(digits), m_data);
0475 --e;
0476 if (old_e > e)
0477 {
0478
0479
0480
0481
0482 digits -= old_e - e;
0483 (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
0484 ps = mpf_get_str(nullptr, &e, 10, static_cast<std::size_t>(digits), m_data);
0485 --e;
0486 }
0487 }
0488 else
0489 {
0490 ps = mpf_get_str(nullptr, &e, 10, 1, m_data);
0491 --e;
0492 unsigned offset = *ps == '-' ? 1 : 0;
0493 ps[offset] = '0';
0494 ps[offset + 1] = 0;
0495 }
0496 }
0497 result = ps;
0498 (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
0499 }
0500 boost::multiprecision::detail::format_float_string(result, e, org_digits, f, mpf_sgn(m_data) == 0);
0501 return result;
0502 }
0503 ~gmp_float_imp() noexcept
0504 {
0505 if (m_data[0]._mp_d)
0506 {
0507 mpf_clear(m_data);
0508 }
0509 }
0510 void negate() noexcept
0511 {
0512 BOOST_MP_ASSERT(m_data[0]._mp_d);
0513 mpf_neg(m_data, m_data);
0514 }
0515 int compare(const gmp_float<digits10>& o) const noexcept
0516 {
0517 BOOST_MP_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d);
0518 return mpf_cmp(m_data, o.m_data);
0519 }
0520 int compare(long i) const noexcept
0521 {
0522 BOOST_MP_ASSERT(m_data[0]._mp_d);
0523 return mpf_cmp_si(m_data, i);
0524 }
0525 int compare(unsigned long i) const noexcept
0526 {
0527 BOOST_MP_ASSERT(m_data[0]._mp_d);
0528 return mpf_cmp_ui(m_data, i);
0529 }
0530 template <class V>
0531 typename std::enable_if<boost::multiprecision::detail::is_arithmetic<V>::value, int>::type compare(V v) const
0532 {
0533 gmp_float<digits10> d;
0534 d = v;
0535 return compare(d);
0536 }
0537 mpf_t& data() noexcept
0538 {
0539 BOOST_MP_ASSERT(m_data[0]._mp_d);
0540 return m_data;
0541 }
0542 const mpf_t& data() const noexcept
0543 {
0544 BOOST_MP_ASSERT(m_data[0]._mp_d);
0545 return m_data;
0546 }
0547
0548 protected:
0549 mpf_t m_data;
0550 static unsigned& get_default_precision() noexcept
0551 {
0552 static BOOST_MP_THREAD_LOCAL unsigned val(get_global_default_precision());
0553 return val;
0554 }
0555 static boost::multiprecision::detail::precision_type& get_global_default_precision() noexcept
0556 {
0557 static boost::multiprecision::detail::precision_type val(50);
0558 return val;
0559 }
0560 #ifndef BOOST_MT_NO_ATOMIC_INT
0561 static std::atomic<variable_precision_options>& get_global_default_options() noexcept
0562 #else
0563 static variable_precision_options& get_global_default_options() noexcept
0564 #endif
0565 {
0566 #ifndef BOOST_MT_NO_ATOMIC_INT
0567 static std::atomic<variable_precision_options> val{variable_precision_options::preserve_related_precision};
0568 #else
0569 static variable_precision_options val{variable_precision_options::preserve_related_precision};
0570 #endif
0571 return val;
0572 }
0573 static variable_precision_options& get_default_options()noexcept
0574 {
0575 static BOOST_MP_THREAD_LOCAL variable_precision_options val(get_global_default_options());
0576 return val;
0577 }
0578 static bool preserve_source_precision() noexcept
0579 {
0580 return get_default_options() >= variable_precision_options::preserve_source_precision;
0581 }
0582 };
0583
0584 class gmp_char_ptr
0585 {
0586 private:
0587 char* ptr_val;
0588 void* (*alloc_func_ptr)(size_t);
0589 void* (*realloc_func_ptr)(void*, size_t, size_t);
0590 void (*free_func_ptr)(void*, size_t);
0591
0592 public:
0593 gmp_char_ptr() = delete;
0594 explicit gmp_char_ptr(char* val_) : ptr_val {val_}
0595 {
0596 mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
0597 }
0598 ~gmp_char_ptr() noexcept
0599 {
0600 (*free_func_ptr)((void*)ptr_val, sizeof(*ptr_val));
0601 ptr_val = nullptr;
0602 }
0603 inline char* get() noexcept { return ptr_val; }
0604 };
0605
0606 }
0607
0608 template <unsigned digits10>
0609 struct gmp_float : public detail::gmp_float_imp<digits10>
0610 {
0611 gmp_float()
0612 {
0613 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
0614 }
0615 gmp_float(const gmp_float& o) : detail::gmp_float_imp<digits10>(o) {}
0616 template <unsigned D>
0617 gmp_float(const gmp_float<D>& o, typename std::enable_if<D <= digits10>::type* = nullptr);
0618 template <unsigned D>
0619 explicit gmp_float(const gmp_float<D>& o, typename std::enable_if<!(D <= digits10)>::type* = nullptr);
0620 gmp_float(const gmp_int& o);
0621 gmp_float(const gmp_rational& o);
0622 gmp_float(const mpf_t val)
0623 {
0624 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
0625 mpf_set(this->m_data, val);
0626 }
0627 gmp_float(const mpz_t val)
0628 {
0629 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
0630 mpf_set_z(this->m_data, val);
0631 }
0632 gmp_float(const mpq_t val)
0633 {
0634 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
0635 mpf_set_q(this->m_data, val);
0636 }
0637
0638 gmp_float(gmp_float&& o) noexcept : detail::gmp_float_imp<digits10>(static_cast<detail::gmp_float_imp<digits10>&&>(o))
0639 {}
0640 gmp_float& operator=(const gmp_float& o)
0641 {
0642 *static_cast<detail::gmp_float_imp<digits10>*>(this) = static_cast<detail::gmp_float_imp<digits10> const&>(o);
0643 return *this;
0644 }
0645 gmp_float& operator=(gmp_float&& o) noexcept
0646 {
0647 *static_cast<detail::gmp_float_imp<digits10>*>(this) = static_cast<detail::gmp_float_imp<digits10>&&>(o);
0648 return *this;
0649 }
0650 template <unsigned D>
0651 gmp_float& operator=(const gmp_float<D>& o);
0652 gmp_float& operator=(const gmp_int& o);
0653 gmp_float& operator=(const gmp_rational& o);
0654 gmp_float& operator=(const mpf_t val)
0655 {
0656 if (this->m_data[0]._mp_d == nullptr)
0657 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
0658 mpf_set(this->m_data, val);
0659 return *this;
0660 }
0661 gmp_float& operator=(const mpz_t val)
0662 {
0663 if (this->m_data[0]._mp_d == nullptr)
0664 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
0665 mpf_set_z(this->m_data, val);
0666 return *this;
0667 }
0668 gmp_float& operator=(const mpq_t val)
0669 {
0670 if (this->m_data[0]._mp_d == nullptr)
0671 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
0672 mpf_set_q(this->m_data, val);
0673 return *this;
0674 }
0675 template <class V>
0676 typename std::enable_if<std::is_assignable<detail::gmp_float_imp<digits10>, V>::value, gmp_float&>::type operator=(const V& v)
0677 {
0678 *static_cast<detail::gmp_float_imp<digits10>*>(this) = v;
0679 return *this;
0680 }
0681 };
0682
0683 template <>
0684 struct gmp_float<0> : public detail::gmp_float_imp<0>
0685 {
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696 private:
0697 unsigned requested_precision;
0698
0699 public:
0700 gmp_float() : requested_precision(get_default_precision())
0701 {
0702 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
0703 }
0704 gmp_float(const mpf_t val) : requested_precision(get_default_precision())
0705 {
0706 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
0707 mpf_set(this->m_data, val);
0708 }
0709 gmp_float(const mpz_t val) : requested_precision(get_default_precision())
0710 {
0711 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
0712 mpf_set_z(this->m_data, val);
0713 }
0714 gmp_float(const mpq_t val) : requested_precision(get_default_precision())
0715 {
0716 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
0717 mpf_set_q(this->m_data, val);
0718 }
0719 gmp_float(const gmp_float& o) : detail::gmp_float_imp<0>(o), requested_precision(preserve_source_precision() ? o.requested_precision : get_default_precision()) {}
0720 template <unsigned D>
0721 gmp_float(const gmp_float<D>& o)
0722 {
0723 mpf_init2(this->m_data, preserve_related_precision() ? mpf_get_prec(o.data()) : multiprecision::detail::digits10_2_2(get_default_precision()));
0724 mpf_set(this->m_data, o.data());
0725 requested_precision = preserve_related_precision() ? D : get_default_precision();
0726 }
0727
0728 gmp_float(gmp_float&& o) noexcept : detail::gmp_float_imp<0>(static_cast<detail::gmp_float_imp<0>&&>(o)), requested_precision((this->get_default_options() != variable_precision_options::preserve_target_precision) ? o.requested_precision : get_default_precision())
0729 {}
0730 gmp_float(const gmp_int& o);
0731 gmp_float(const gmp_rational& o);
0732 gmp_float(const gmp_float& o, unsigned digits10) : requested_precision(digits10)
0733 {
0734 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
0735 mpf_set(this->m_data, o.data());
0736 }
0737 template <class V>
0738 gmp_float(const V& o, unsigned digits10) : requested_precision(digits10)
0739 {
0740 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
0741 *this = o;
0742 }
0743
0744 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
0745
0746
0747
0748 template <class Traits>
0749 gmp_float(const std::basic_string_view<char, Traits>& o, unsigned digits10) : requested_precision(digits10)
0750 {
0751 using default_ops::assign_from_string_view;
0752 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
0753 assign_from_string_view(*this, o);
0754 }
0755 #endif
0756 gmp_float& operator=(const gmp_float& o)
0757 {
0758 *static_cast<detail::gmp_float_imp<0>*>(this) = static_cast<detail::gmp_float_imp<0> const&>(o);
0759 if(preserve_source_precision())
0760 requested_precision = o.requested_precision;
0761 return *this;
0762 }
0763
0764 gmp_float& operator=(gmp_float&& o) noexcept
0765 {
0766 *static_cast<detail::gmp_float_imp<0>*>(this) = static_cast<detail::gmp_float_imp<0>&&>(o);
0767 if ((this->get_default_options() != variable_precision_options::preserve_target_precision))
0768 requested_precision = o.requested_precision;
0769 return *this;
0770 }
0771 template <unsigned D>
0772 gmp_float& operator=(const gmp_float<D>& o)
0773 {
0774 if (this->m_data[0]._mp_d == nullptr)
0775 {
0776 mpf_init2(this->m_data, preserve_related_precision() ? mpf_get_prec(o.data()) : multiprecision::detail::digits10_2_2(get_default_precision()));
0777 }
0778 else if(preserve_related_precision())
0779 {
0780 mpf_set_prec(this->m_data, mpf_get_prec(o.data()));
0781 }
0782 mpf_set(this->m_data, o.data());
0783 if (preserve_related_precision())
0784 requested_precision = D;
0785 return *this;
0786 }
0787 gmp_float& operator=(const gmp_int& o);
0788 gmp_float& operator=(const gmp_rational& o);
0789 gmp_float& operator=(const mpf_t val)
0790 {
0791 if (this->m_data[0]._mp_d == nullptr)
0792 {
0793 requested_precision = get_default_precision();
0794 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
0795 }
0796 mpf_set(this->m_data, val);
0797 return *this;
0798 }
0799 gmp_float& operator=(const mpz_t val)
0800 {
0801 if (this->m_data[0]._mp_d == nullptr)
0802 {
0803 requested_precision = get_default_precision();
0804 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
0805 }
0806 mpf_set_z(this->m_data, val);
0807 return *this;
0808 }
0809 gmp_float& operator=(const mpq_t val)
0810 {
0811 if (this->m_data[0]._mp_d == nullptr)
0812 {
0813 requested_precision = get_default_precision();
0814 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
0815 }
0816 mpf_set_q(this->m_data, val);
0817 return *this;
0818 }
0819 template <class V>
0820 typename std::enable_if<std::is_assignable<detail::gmp_float_imp<0>, V>::value, gmp_float&>::type operator=(const V& v)
0821 {
0822 constexpr unsigned d10 = std::is_floating_point<V>::value ?
0823 std::numeric_limits<V>::digits10 :
0824 std::numeric_limits<V>::digits10 ? 1 + std::numeric_limits<V>::digits10 :
0825 1 + boost::multiprecision::detail::digits2_2_10(std::numeric_limits<V>::digits);
0826 if((thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision) && (precision() < d10))
0827 this->precision(d10);
0828 *static_cast<detail::gmp_float_imp<0>*>(this) = v;
0829 return *this;
0830 }
0831 static unsigned default_precision() noexcept
0832 {
0833 return get_global_default_precision();
0834 }
0835 static void default_precision(unsigned v) noexcept
0836 {
0837 get_global_default_precision() = v;
0838 }
0839 static unsigned thread_default_precision() noexcept
0840 {
0841 return get_default_precision();
0842 }
0843 static void thread_default_precision(unsigned v) noexcept
0844 {
0845 get_default_precision() = v;
0846 }
0847 unsigned precision() const noexcept
0848 {
0849 return requested_precision;
0850 }
0851 void precision(unsigned digits10) noexcept
0852 {
0853 requested_precision = digits10;
0854 mpf_set_prec(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
0855 }
0856
0857
0858
0859 static variable_precision_options default_variable_precision_options()noexcept
0860 {
0861 return get_global_default_options();
0862 }
0863 static variable_precision_options thread_default_variable_precision_options()noexcept
0864 {
0865 return get_default_options();
0866 }
0867 static void default_variable_precision_options(variable_precision_options opts)
0868 {
0869 get_global_default_options() = opts;
0870 }
0871 static void thread_default_variable_precision_options(variable_precision_options opts)
0872 {
0873 get_default_options() = opts;
0874 }
0875 static bool preserve_source_precision()
0876 {
0877 return get_default_options() >= variable_precision_options::preserve_source_precision;
0878 }
0879 static bool preserve_related_precision()
0880 {
0881 return get_default_options() >= variable_precision_options::preserve_related_precision;
0882 }
0883 static bool preserve_all_precision()
0884 {
0885 return get_default_options() >= variable_precision_options::preserve_all_precision;
0886 }
0887
0888
0889
0890 void swap(gmp_float& o)
0891 {
0892 std::swap(requested_precision, o.requested_precision);
0893 gmp_float_imp<0>::swap(o);
0894 }
0895 };
0896
0897 template <unsigned digits10, class T>
0898 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_eq(const gmp_float<digits10>& a, const T& b) noexcept
0899 {
0900 return a.compare(b) == 0;
0901 }
0902 template <unsigned digits10, class T>
0903 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_lt(const gmp_float<digits10>& a, const T& b) noexcept
0904 {
0905 return a.compare(b) < 0;
0906 }
0907 template <unsigned digits10, class T>
0908 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_gt(const gmp_float<digits10>& a, const T& b) noexcept
0909 {
0910 return a.compare(b) > 0;
0911 }
0912
0913 template <unsigned D1, unsigned D2>
0914 inline void eval_add(gmp_float<D1>& result, const gmp_float<D2>& o)
0915 {
0916 mpf_add(result.data(), result.data(), o.data());
0917 }
0918 template <unsigned D1, unsigned D2>
0919 inline void eval_subtract(gmp_float<D1>& result, const gmp_float<D2>& o)
0920 {
0921 mpf_sub(result.data(), result.data(), o.data());
0922 }
0923 template <unsigned D1, unsigned D2>
0924 inline void eval_multiply(gmp_float<D1>& result, const gmp_float<D2>& o)
0925 {
0926 mpf_mul(result.data(), result.data(), o.data());
0927 }
0928 template <unsigned digits10>
0929 inline bool eval_is_zero(const gmp_float<digits10>& val) noexcept
0930 {
0931 return mpf_sgn(val.data()) == 0;
0932 }
0933 template <unsigned D1, unsigned D2>
0934 inline void eval_divide(gmp_float<D1>& result, const gmp_float<D2>& o)
0935 {
0936 if (eval_is_zero(o))
0937 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
0938 mpf_div(result.data(), result.data(), o.data());
0939 }
0940 template <unsigned digits10>
0941 inline void eval_add(gmp_float<digits10>& result, unsigned long i)
0942 {
0943 mpf_add_ui(result.data(), result.data(), i);
0944 }
0945 template <unsigned digits10>
0946 inline void eval_subtract(gmp_float<digits10>& result, unsigned long i)
0947 {
0948 mpf_sub_ui(result.data(), result.data(), i);
0949 }
0950 template <unsigned digits10>
0951 inline void eval_multiply(gmp_float<digits10>& result, unsigned long i)
0952 {
0953 mpf_mul_ui(result.data(), result.data(), i);
0954 }
0955 template <unsigned digits10>
0956 inline void eval_divide(gmp_float<digits10>& result, unsigned long i)
0957 {
0958 if (i == 0)
0959 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
0960 mpf_div_ui(result.data(), result.data(), i);
0961 }
0962 template <unsigned digits10>
0963 inline void eval_add(gmp_float<digits10>& result, long i)
0964 {
0965 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
0966
0967 if (i > 0)
0968 mpf_add_ui(result.data(), result.data(), static_cast<local_uint_type>(i));
0969 else if (i < 0)
0970 mpf_sub_ui(result.data(), result.data(), static_cast<local_uint_type>(-i));
0971 }
0972 template <unsigned digits10>
0973 inline void eval_subtract(gmp_float<digits10>& result, long i)
0974 {
0975 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
0976
0977 if (i > 0)
0978 mpf_sub_ui(result.data(), result.data(), static_cast<local_uint_type>(i));
0979 else if (i < 0)
0980 mpf_add_ui(result.data(), result.data(), static_cast<local_uint_type>(-i));
0981 }
0982 template <unsigned digits10>
0983 inline void eval_multiply(gmp_float<digits10>& result, long i)
0984 {
0985 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
0986
0987 mpf_mul_ui(result.data(), result.data(), static_cast<local_uint_type>(boost::multiprecision::detail::unsigned_abs(i)));
0988
0989 if (i < 0)
0990 mpf_neg(result.data(), result.data());
0991 }
0992 template <unsigned digits10>
0993 inline void eval_divide(gmp_float<digits10>& result, long i)
0994 {
0995 if (i == 0)
0996 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
0997
0998 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
0999
1000 mpf_div_ui(result.data(), result.data(), static_cast<local_uint_type>(boost::multiprecision::detail::unsigned_abs(i)));
1001
1002 if (i < 0)
1003 mpf_neg(result.data(), result.data());
1004 }
1005
1006
1007
1008 template <unsigned D1, unsigned D2, unsigned D3>
1009 inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
1010 {
1011 mpf_add(a.data(), x.data(), y.data());
1012 }
1013 template <unsigned D1, unsigned D2>
1014 inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
1015 {
1016 mpf_add_ui(a.data(), x.data(), y);
1017 }
1018 template <unsigned D1, unsigned D2>
1019 inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
1020 {
1021 if (y < 0)
1022 mpf_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
1023 else
1024 mpf_add_ui(a.data(), x.data(), y);
1025 }
1026 template <unsigned D1, unsigned D2>
1027 inline void eval_add(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
1028 {
1029 mpf_add_ui(a.data(), y.data(), x);
1030 }
1031 template <unsigned D1, unsigned D2>
1032 inline void eval_add(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
1033 {
1034 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1035
1036 if (x < 0)
1037 {
1038 mpf_ui_sub(a.data(), static_cast<local_uint_type>(-x), y.data());
1039 mpf_neg(a.data(), a.data());
1040 }
1041 else
1042 mpf_add_ui(a.data(), y.data(), static_cast<local_uint_type>(x));
1043 }
1044 template <unsigned D1, unsigned D2, unsigned D3>
1045 inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
1046 {
1047 mpf_sub(a.data(), x.data(), y.data());
1048 }
1049 template <unsigned D1, unsigned D2>
1050 inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
1051 {
1052 mpf_sub_ui(a.data(), x.data(), y);
1053 }
1054 template <unsigned D1, unsigned D2>
1055 inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
1056 {
1057 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1058
1059 if (y < 0)
1060 mpf_add_ui(a.data(), x.data(), static_cast<local_uint_type>(-y));
1061 else
1062 mpf_sub_ui(a.data(), x.data(), static_cast<local_uint_type>(y));
1063 }
1064 template <unsigned D1, unsigned D2>
1065 inline void eval_subtract(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
1066 {
1067 mpf_ui_sub(a.data(), x, y.data());
1068 }
1069 template <unsigned D1, unsigned D2>
1070 inline void eval_subtract(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
1071 {
1072 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1073
1074 if (x < 0)
1075 {
1076 mpf_add_ui(a.data(), y.data(), static_cast<local_uint_type>(-x));
1077 mpf_neg(a.data(), a.data());
1078 }
1079 else
1080 mpf_ui_sub(a.data(), static_cast<local_uint_type>(x), y.data());
1081 }
1082
1083 template <unsigned D1, unsigned D2, unsigned D3>
1084 inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
1085 {
1086 mpf_mul(a.data(), x.data(), y.data());
1087 }
1088 template <unsigned D1, unsigned D2>
1089 inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
1090 {
1091 mpf_mul_ui(a.data(), x.data(), y);
1092 }
1093 template <unsigned D1, unsigned D2>
1094 inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
1095 {
1096 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1097
1098 if (y < 0)
1099 {
1100 mpf_mul_ui(a.data(), x.data(), static_cast<local_uint_type>(-y));
1101 a.negate();
1102 }
1103 else
1104 mpf_mul_ui(a.data(), x.data(), static_cast<local_uint_type>(y));
1105 }
1106 template <unsigned D1, unsigned D2>
1107 inline void eval_multiply(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
1108 {
1109 mpf_mul_ui(a.data(), y.data(), x);
1110 }
1111 template <unsigned D1, unsigned D2>
1112 inline void eval_multiply(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
1113 {
1114 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1115
1116 if (x < 0)
1117 {
1118 mpf_mul_ui(a.data(), y.data(), static_cast<local_uint_type>(-x));
1119 mpf_neg(a.data(), a.data());
1120 }
1121 else
1122 mpf_mul_ui(a.data(), y.data(), static_cast<local_uint_type>(x));
1123 }
1124
1125 template <unsigned D1, unsigned D2, unsigned D3>
1126 inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
1127 {
1128 if (eval_is_zero(y))
1129 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1130 mpf_div(a.data(), x.data(), y.data());
1131 }
1132 template <unsigned D1, unsigned D2>
1133 inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
1134 {
1135 if (y == 0)
1136 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1137 mpf_div_ui(a.data(), x.data(), y);
1138 }
1139 template <unsigned D1, unsigned D2>
1140 inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
1141 {
1142 if (y == 0)
1143 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1144
1145 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1146
1147 if (y < 0)
1148 {
1149 mpf_div_ui(a.data(), x.data(), static_cast<local_uint_type>(-y));
1150 a.negate();
1151 }
1152 else
1153 mpf_div_ui(a.data(), x.data(), static_cast<local_uint_type>(y));
1154 }
1155 template <unsigned D1, unsigned D2>
1156 inline void eval_divide(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
1157 {
1158 if (eval_is_zero(y))
1159 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1160 mpf_ui_div(a.data(), x, y.data());
1161 }
1162 template <unsigned D1, unsigned D2>
1163 inline void eval_divide(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
1164 {
1165 if (eval_is_zero(y))
1166 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1167 if (x < 0)
1168 {
1169 mpf_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data());
1170 mpf_neg(a.data(), a.data());
1171 }
1172 else
1173 {
1174 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1175
1176 mpf_ui_div(a.data(), static_cast<local_uint_type>(x), y.data());
1177 }
1178 }
1179
1180 template <unsigned digits10>
1181 inline int eval_get_sign(const gmp_float<digits10>& val) noexcept
1182 {
1183 return mpf_sgn(val.data());
1184 }
1185
1186 template <unsigned digits10>
1187 inline void eval_convert_to(unsigned long* result, const gmp_float<digits10>& val) noexcept
1188 {
1189 if (0 == mpf_fits_ulong_p(val.data()))
1190 *result = (std::numeric_limits<unsigned long>::max)();
1191 else
1192 *result = static_cast<unsigned long>(mpf_get_ui(val.data()));
1193 }
1194 template <unsigned digits10>
1195 inline void eval_convert_to(long* result, const gmp_float<digits10>& val) noexcept
1196 {
1197 if (0 == mpf_fits_slong_p(val.data()))
1198 {
1199 *result = (std::numeric_limits<long>::max)();
1200 *result *= mpf_sgn(val.data());
1201 }
1202 else
1203 *result = static_cast<long>(mpf_get_si(val.data()));
1204 }
1205 #ifdef BOOST_MP_STANDALONE
1206 template <unsigned digits10>
1207 inline void eval_convert_to(long double* result, const gmp_float<digits10>& val) noexcept
1208 {
1209 mp_exp_t exp = 0;
1210
1211 detail::gmp_char_ptr val_char_ptr {mpf_get_str(nullptr, &exp, 10, LDBL_DIG, val.data())};
1212
1213 auto temp_string = std::string(val_char_ptr.get());
1214 if(exp > 0 && static_cast<std::size_t>(exp) < temp_string.size())
1215 {
1216 if(temp_string.front() == '-')
1217 {
1218 ++exp;
1219 }
1220
1221 temp_string.insert(static_cast<std::size_t>(exp), static_cast<std::size_t>(1u), '.');
1222 }
1223
1224 *result = std::strtold(temp_string.c_str(), nullptr);
1225
1226 if((temp_string.size() == 2ul && *result < 0.0l) ||
1227 (static_cast<std::size_t>(exp) > temp_string.size()))
1228 {
1229 *result *= std::pow(10l, exp-1);
1230 }
1231 }
1232 #endif
1233 template <unsigned digits10>
1234 inline void eval_convert_to(double* result, const gmp_float<digits10>& val) noexcept
1235 {
1236 *result = mpf_get_d(val.data());
1237 }
1238 #ifdef BOOST_HAS_LONG_LONG
1239 template <unsigned digits10>
1240 inline void eval_convert_to(long long* result, const gmp_float<digits10>& val)
1241 {
1242 gmp_float<digits10> t(val);
1243 if (eval_get_sign(t) < 0)
1244 t.negate();
1245
1246 long digits = std::numeric_limits<long long>::digits - std::numeric_limits<long>::digits;
1247
1248 if (digits > 0)
1249 mpf_div_2exp(t.data(), t.data(), digits);
1250
1251 if (!mpf_fits_slong_p(t.data()))
1252 {
1253 if (eval_get_sign(val) < 0)
1254 *result = (std::numeric_limits<long long>::min)();
1255 else
1256 *result = (std::numeric_limits<long long>::max)();
1257 return;
1258 };
1259
1260 *result = mpf_get_si(t.data());
1261 while (digits > 0)
1262 {
1263 *result <<= digits;
1264 digits -= std::numeric_limits<unsigned long>::digits;
1265 mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits<unsigned long>::digits : std::numeric_limits<unsigned long>::digits + digits);
1266 unsigned long l = static_cast<unsigned long>(mpf_get_ui(t.data()));
1267 if (digits < 0)
1268 l >>= -digits;
1269 *result |= l;
1270 }
1271 if (eval_get_sign(val) < 0)
1272 *result = -*result;
1273 }
1274 template <unsigned digits10>
1275 inline void eval_convert_to(unsigned long long* result, const gmp_float<digits10>& val)
1276 {
1277 gmp_float<digits10> t(val);
1278
1279 long digits = std::numeric_limits<long long>::digits - std::numeric_limits<long>::digits;
1280
1281 if (digits > 0)
1282 mpf_div_2exp(t.data(), t.data(), digits);
1283
1284 if (!mpf_fits_ulong_p(t.data()))
1285 {
1286 *result = (std::numeric_limits<long long>::max)();
1287 return;
1288 }
1289
1290 *result = mpf_get_ui(t.data());
1291 while (digits > 0)
1292 {
1293 *result <<= digits;
1294 digits -= std::numeric_limits<unsigned long>::digits;
1295 mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits<unsigned long>::digits : std::numeric_limits<unsigned long>::digits + digits);
1296 unsigned long l = static_cast<unsigned long>(mpf_get_ui(t.data()));
1297 if (digits < 0)
1298 l >>= -digits;
1299 *result |= l;
1300 }
1301 }
1302 #endif
1303
1304
1305 #ifdef BOOST_HAS_FLOAT128
1306 template <unsigned digits10>
1307 inline void eval_convert_to(float128_type* result, const gmp_float<digits10>& val)
1308 {
1309 *result = float128_procs::strtoflt128(val.str(0, std::ios_base::scientific).c_str(), nullptr);
1310 }
1311 #endif
1312
1313
1314
1315
1316
1317 template <unsigned Digits10>
1318 inline void eval_sqrt(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1319 {
1320 mpf_sqrt(result.data(), val.data());
1321 }
1322
1323 template <unsigned Digits10>
1324 inline void eval_abs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1325 {
1326 mpf_abs(result.data(), val.data());
1327 }
1328
1329 template <unsigned Digits10>
1330 inline void eval_fabs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1331 {
1332 mpf_abs(result.data(), val.data());
1333 }
1334 template <unsigned Digits10>
1335 inline void eval_ceil(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1336 {
1337 mpf_ceil(result.data(), val.data());
1338 }
1339 template <unsigned Digits10>
1340 inline void eval_floor(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1341 {
1342 mpf_floor(result.data(), val.data());
1343 }
1344 template <unsigned Digits10>
1345 inline void eval_trunc(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1346 {
1347 mpf_trunc(result.data(), val.data());
1348 }
1349 template <unsigned Digits10>
1350 inline void eval_ldexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long e)
1351 {
1352 if (e > 0)
1353 mpf_mul_2exp(result.data(), val.data(), static_cast<mp_bitcnt_t>(e));
1354 else if (e < 0)
1355 mpf_div_2exp(result.data(), val.data(), static_cast<mp_bitcnt_t>(-e));
1356 else
1357 result = val;
1358 }
1359 template <unsigned Digits10>
1360 inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, int* e)
1361 {
1362 #if (BOOST_MP_MPIR_VERSION >= 20600) && (BOOST_MP_MPIR_VERSION < 30000)
1363 mpir_si v;
1364 mpf_get_d_2exp(&v, val.data());
1365 #else
1366 long v;
1367 mpf_get_d_2exp(&v, val.data());
1368 #endif
1369 *e = static_cast<int>(v);
1370 eval_ldexp(result, val, -v);
1371 }
1372 template <unsigned Digits10>
1373 inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long* e)
1374 {
1375 #if (BOOST_MP_MPIR_VERSION >= 20600) && (BOOST_MP_MPIR_VERSION < 30000)
1376 mpir_si v;
1377 mpf_get_d_2exp(&v, val.data());
1378 *e = v;
1379 eval_ldexp(result, val, -v);
1380 #else
1381 mpf_get_d_2exp(e, val.data());
1382 eval_ldexp(result, val, -*e);
1383 #endif
1384 }
1385
1386 template <unsigned Digits10>
1387 inline std::size_t hash_value(const gmp_float<Digits10>& val)
1388 {
1389 std::size_t result = 0;
1390 for (int i = 0; i < std::abs(val.data()[0]._mp_size); ++i)
1391 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_d[i]);
1392 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_exp, val.data()[0]._mp_size);
1393 return result;
1394 }
1395
1396 struct gmp_int
1397 {
1398 #ifdef BOOST_HAS_LONG_LONG
1399 using signed_types = std::tuple<long, long long> ;
1400 using unsigned_types = std::tuple<unsigned long, unsigned long long>;
1401 #else
1402 using signed_types = std::tuple<long> ;
1403 using unsigned_types = std::tuple<unsigned long>;
1404 #endif
1405 using float_types = std::tuple<double, long double>;
1406
1407 gmp_int()
1408 {
1409 mpz_init(this->m_data);
1410 }
1411 gmp_int(const gmp_int& o)
1412 {
1413 if (o.m_data[0]._mp_d)
1414 mpz_init_set(m_data, o.m_data);
1415 else
1416 mpz_init(this->m_data);
1417 }
1418
1419 gmp_int(gmp_int&& o) noexcept
1420 {
1421 m_data[0] = o.m_data[0];
1422 o.m_data[0]._mp_d = nullptr;
1423 }
1424 explicit gmp_int(const mpf_t val)
1425 {
1426 mpz_init(this->m_data);
1427 mpz_set_f(this->m_data, val);
1428 }
1429 gmp_int(const mpz_t val)
1430 {
1431 mpz_init_set(this->m_data, val);
1432 }
1433 gmp_int(long i)
1434 {
1435 mpz_init_set_si(this->m_data, i);
1436 }
1437 gmp_int(unsigned long i)
1438 {
1439 mpz_init_set_ui(this->m_data, i);
1440 }
1441 explicit gmp_int(const mpq_t val)
1442 {
1443 mpz_init(this->m_data);
1444 mpz_set_q(this->m_data, val);
1445 }
1446 template <unsigned Digits10>
1447 explicit gmp_int(const gmp_float<Digits10>& o)
1448 {
1449 mpz_init(this->m_data);
1450 mpz_set_f(this->m_data, o.data());
1451 }
1452 explicit gmp_int(const gmp_rational& o);
1453 gmp_int& operator=(const gmp_int& o)
1454 {
1455 if (m_data[0]._mp_d == nullptr)
1456 mpz_init(this->m_data);
1457 mpz_set(m_data, o.m_data);
1458 return *this;
1459 }
1460
1461 gmp_int& operator=(gmp_int&& o) noexcept
1462 {
1463 mpz_swap(m_data, o.m_data);
1464 return *this;
1465 }
1466 #ifdef BOOST_HAS_LONG_LONG
1467 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
1468 gmp_int& operator=(unsigned long long i)
1469 {
1470 *this = static_cast<unsigned long>(i);
1471 return *this;
1472 }
1473 #else
1474 gmp_int& operator=(unsigned long long i)
1475 {
1476 if (m_data[0]._mp_d == nullptr)
1477 mpz_init(this->m_data);
1478 unsigned long long mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
1479 unsigned shift = 0;
1480 mpz_t t;
1481 mpz_set_ui(m_data, 0);
1482 mpz_init_set_ui(t, 0);
1483 while (i)
1484 {
1485 mpz_set_ui(t, static_cast<unsigned long>(i & mask));
1486 if (shift)
1487 mpz_mul_2exp(t, t, shift);
1488 mpz_add(m_data, m_data, t);
1489 shift += std::numeric_limits<unsigned long>::digits;
1490 i >>= std::numeric_limits<unsigned long>::digits;
1491 }
1492 mpz_clear(t);
1493 return *this;
1494 }
1495 #endif
1496 gmp_int& operator=(long long i)
1497 {
1498 if (m_data[0]._mp_d == nullptr)
1499 mpz_init(this->m_data);
1500 bool neg = i < 0;
1501 *this = boost::multiprecision::detail::unsigned_abs(i);
1502 if (neg)
1503 mpz_neg(m_data, m_data);
1504 return *this;
1505 }
1506 #endif
1507 #ifdef BOOST_HAS_INT128
1508 gmp_int& operator=(uint128_type i)
1509 {
1510 if (m_data[0]._mp_d == nullptr)
1511 mpz_init(this->m_data);
1512 uint128_type mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
1513 unsigned shift = 0;
1514 mpz_t t;
1515 mpz_set_ui(m_data, 0);
1516 mpz_init_set_ui(t, 0);
1517 while (i)
1518 {
1519 mpz_set_ui(t, static_cast<unsigned long>(i & mask));
1520 if (shift)
1521 mpz_mul_2exp(t, t, shift);
1522 mpz_add(m_data, m_data, t);
1523 shift += std::numeric_limits<unsigned long>::digits;
1524 i >>= std::numeric_limits<unsigned long>::digits;
1525 }
1526 mpz_clear(t);
1527 return *this;
1528 }
1529 gmp_int& operator=(int128_type i)
1530 {
1531 if (m_data[0]._mp_d == nullptr)
1532 mpz_init(this->m_data);
1533 bool neg = i < 0;
1534 *this = boost::multiprecision::detail::unsigned_abs(i);
1535 if (neg)
1536 mpz_neg(m_data, m_data);
1537 return *this;
1538 }
1539 #endif
1540 gmp_int& operator=(unsigned long i)
1541 {
1542 if (m_data[0]._mp_d == nullptr)
1543 mpz_init(this->m_data);
1544 mpz_set_ui(m_data, i);
1545 return *this;
1546 }
1547 gmp_int& operator=(long i)
1548 {
1549 if (m_data[0]._mp_d == nullptr)
1550 mpz_init(this->m_data);
1551 mpz_set_si(m_data, i);
1552 return *this;
1553 }
1554 gmp_int& operator=(double d)
1555 {
1556 if (m_data[0]._mp_d == nullptr)
1557 mpz_init(this->m_data);
1558 mpz_set_d(m_data, d);
1559 return *this;
1560 }
1561 template <class F>
1562 gmp_int& assign_float(F a)
1563 {
1564 BOOST_MP_FLOAT128_USING using std::floor; using std::frexp; using std::ldexp;
1565
1566 if (m_data[0]._mp_d == nullptr)
1567 mpz_init(this->m_data);
1568
1569 if (a == 0)
1570 {
1571 mpz_set_si(m_data, 0);
1572 return *this;
1573 }
1574
1575 if (a == 1)
1576 {
1577 mpz_set_si(m_data, 1);
1578 return *this;
1579 }
1580
1581 BOOST_MP_ASSERT(!BOOST_MP_ISINF(a));
1582 BOOST_MP_ASSERT(!BOOST_MP_ISNAN(a));
1583
1584 int e;
1585 F f, term;
1586 mpz_set_ui(m_data, 0u);
1587
1588 f = frexp(a, &e);
1589
1590 constexpr int shift = std::numeric_limits<int>::digits - 1;
1591
1592 while (f != static_cast<F>(0.0f))
1593 {
1594
1595 f = ldexp(f, shift);
1596 term = floor(f);
1597 e -= shift;
1598 mpz_mul_2exp(m_data, m_data, shift);
1599 if (term > 0)
1600 mpz_add_ui(m_data, m_data, static_cast<unsigned>(term));
1601 else
1602 mpz_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
1603 f -= term;
1604 }
1605 if (e > 0)
1606 mpz_mul_2exp(m_data, m_data, static_cast<mp_bitcnt_t>(e));
1607 else if (e < 0)
1608 mpz_div_2exp(m_data, m_data, static_cast<mp_bitcnt_t>(-e));
1609 return *this;
1610 }
1611 gmp_int& operator=(long double a)
1612 {
1613 return assign_float(a);
1614 }
1615 gmp_int& operator=(const char* s)
1616 {
1617 if (m_data[0]._mp_d == nullptr)
1618 mpz_init(this->m_data);
1619 std::size_t n = s ? std::strlen(s) : 0;
1620 int radix = 10;
1621 if (n && (*s == '0'))
1622 {
1623 if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
1624 {
1625 radix = 16;
1626 s += 2;
1627 n -= 2;
1628 }
1629 else
1630 {
1631 radix = 8;
1632 n -= 1;
1633 }
1634 }
1635 if (n)
1636 {
1637 if (0 != mpz_set_str(m_data, s, radix))
1638 BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid integer.")));
1639 }
1640 else
1641 mpz_set_ui(m_data, 0);
1642 return *this;
1643 }
1644 #ifdef BOOST_HAS_FLOAT128
1645 gmp_int& operator=(float128_type a)
1646 {
1647 return assign_float(a);
1648 }
1649 #endif
1650 gmp_int& operator=(const mpf_t val)
1651 {
1652 if (m_data[0]._mp_d == nullptr)
1653 mpz_init(this->m_data);
1654 mpz_set_f(this->m_data, val);
1655 return *this;
1656 }
1657 gmp_int& operator=(const mpz_t val)
1658 {
1659 if (m_data[0]._mp_d == nullptr)
1660 mpz_init(this->m_data);
1661 mpz_set(this->m_data, val);
1662 return *this;
1663 }
1664 gmp_int& operator=(const mpq_t val)
1665 {
1666 if (m_data[0]._mp_d == nullptr)
1667 mpz_init(this->m_data);
1668 mpz_set_q(this->m_data, val);
1669 return *this;
1670 }
1671 template <unsigned Digits10>
1672 gmp_int& operator=(const gmp_float<Digits10>& o)
1673 {
1674 if (m_data[0]._mp_d == nullptr)
1675 mpz_init(this->m_data);
1676 mpz_set_f(this->m_data, o.data());
1677 return *this;
1678 }
1679 gmp_int& operator=(const gmp_rational& o);
1680 void swap(gmp_int& o)
1681 {
1682 mpz_swap(m_data, o.m_data);
1683 }
1684 std::string str(std::streamsize , std::ios_base::fmtflags f) const
1685 {
1686 BOOST_MP_ASSERT(m_data[0]._mp_d);
1687
1688 int base = 10;
1689 if ((f & std::ios_base::oct) == std::ios_base::oct)
1690 base = 8;
1691 else if ((f & std::ios_base::hex) == std::ios_base::hex)
1692 base = 16;
1693
1694
1695
1696 if ((base != 10) && (mpz_sgn(m_data) < 0))
1697 BOOST_MP_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers"));
1698 void* (*alloc_func_ptr)(size_t);
1699 void* (*realloc_func_ptr)(void*, size_t, size_t);
1700 void (*free_func_ptr)(void*, size_t);
1701 const char* ps = mpz_get_str(nullptr, base, m_data);
1702 std::string s = ps;
1703 mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
1704 (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
1705 if (f & std::ios_base::uppercase)
1706 for (size_t i = 0; i < s.length(); ++i)
1707 s[i] = static_cast<char>(std::toupper(s[i]));
1708 if ((base != 10) && (f & std::ios_base::showbase))
1709 {
1710 int pos = s[0] == '-' ? 1 : 0;
1711 const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x";
1712 s.insert(static_cast<std::string::size_type>(pos), pp);
1713 }
1714 if ((f & std::ios_base::showpos) && (s[0] != '-'))
1715 s.insert(static_cast<std::string::size_type>(0), 1, '+');
1716
1717 return s;
1718 }
1719 ~gmp_int() noexcept
1720 {
1721 if (m_data[0]._mp_d)
1722 mpz_clear(m_data);
1723 }
1724 void negate() noexcept
1725 {
1726 BOOST_MP_ASSERT(m_data[0]._mp_d);
1727 mpz_neg(m_data, m_data);
1728 }
1729 int compare(const gmp_int& o) const noexcept
1730 {
1731 BOOST_MP_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d);
1732 return mpz_cmp(m_data, o.m_data);
1733 }
1734 int compare(long i) const noexcept
1735 {
1736 BOOST_MP_ASSERT(m_data[0]._mp_d);
1737 return mpz_cmp_si(m_data, i);
1738 }
1739 int compare(unsigned long i) const noexcept
1740 {
1741 BOOST_MP_ASSERT(m_data[0]._mp_d);
1742 return mpz_cmp_ui(m_data, i);
1743 }
1744 template <class V>
1745 int compare(V v) const
1746 {
1747 gmp_int d;
1748 d = v;
1749 return compare(d);
1750 }
1751 mpz_t& data() noexcept
1752 {
1753 BOOST_MP_ASSERT(m_data[0]._mp_d);
1754 return m_data;
1755 }
1756 const mpz_t& data() const noexcept
1757 {
1758 BOOST_MP_ASSERT(m_data[0]._mp_d);
1759 return m_data;
1760 }
1761
1762 protected:
1763 mpz_t m_data;
1764 };
1765
1766 template <class T>
1767 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_eq(const gmp_int& a, const T& b)
1768 {
1769 return a.compare(b) == 0;
1770 }
1771 template <class T>
1772 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_lt(const gmp_int& a, const T& b)
1773 {
1774 return a.compare(b) < 0;
1775 }
1776 template <class T>
1777 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_gt(const gmp_int& a, const T& b)
1778 {
1779 return a.compare(b) > 0;
1780 }
1781
1782 inline bool eval_is_zero(const gmp_int& val)
1783 {
1784 return mpz_sgn(val.data()) == 0;
1785 }
1786 inline void eval_add(gmp_int& t, const gmp_int& o)
1787 {
1788 mpz_add(t.data(), t.data(), o.data());
1789 }
1790 inline void eval_multiply_add(gmp_int& t, const gmp_int& a, const gmp_int& b)
1791 {
1792 mpz_addmul(t.data(), a.data(), b.data());
1793 }
1794 inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, const gmp_int& b)
1795 {
1796 mpz_submul(t.data(), a.data(), b.data());
1797 }
1798 inline void eval_subtract(gmp_int& t, const gmp_int& o)
1799 {
1800 mpz_sub(t.data(), t.data(), o.data());
1801 }
1802 inline void eval_multiply(gmp_int& t, const gmp_int& o)
1803 {
1804 mpz_mul(t.data(), t.data(), o.data());
1805 }
1806 inline void eval_divide(gmp_int& t, const gmp_int& o)
1807 {
1808 if (eval_is_zero(o))
1809 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1810 mpz_tdiv_q(t.data(), t.data(), o.data());
1811 }
1812 inline void eval_modulus(gmp_int& t, const gmp_int& o)
1813 {
1814 mpz_tdiv_r(t.data(), t.data(), o.data());
1815 }
1816 inline void eval_add(gmp_int& t, unsigned long i)
1817 {
1818 mpz_add_ui(t.data(), t.data(), i);
1819 }
1820 inline void eval_multiply_add(gmp_int& t, const gmp_int& a, unsigned long i)
1821 {
1822 mpz_addmul_ui(t.data(), a.data(), i);
1823 }
1824 inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, unsigned long i)
1825 {
1826 mpz_submul_ui(t.data(), a.data(), i);
1827 }
1828 inline void eval_subtract(gmp_int& t, unsigned long i)
1829 {
1830 mpz_sub_ui(t.data(), t.data(), i);
1831 }
1832 inline void eval_multiply(gmp_int& t, unsigned long i)
1833 {
1834 mpz_mul_ui(t.data(), t.data(), i);
1835 }
1836 inline void eval_modulus(gmp_int& t, unsigned long i)
1837 {
1838 mpz_tdiv_r_ui(t.data(), t.data(), i);
1839 }
1840 inline void eval_divide(gmp_int& t, unsigned long i)
1841 {
1842 if (i == 0)
1843 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1844 mpz_tdiv_q_ui(t.data(), t.data(), i);
1845 }
1846 inline void eval_add(gmp_int& t, long i)
1847 {
1848 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1849
1850 if (i > 0)
1851 mpz_add_ui(t.data(), t.data(), static_cast<local_uint_type>(i));
1852 else if (i < 0)
1853 mpz_sub_ui(t.data(), t.data(), static_cast<local_uint_type>(-i));
1854 }
1855 inline void eval_multiply_add(gmp_int& t, const gmp_int& a, long i)
1856 {
1857 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1858
1859 if (i > 0)
1860 mpz_addmul_ui(t.data(), a.data(), static_cast<local_uint_type>(i));
1861 else
1862 mpz_submul_ui(t.data(), a.data(), static_cast<local_uint_type>(-i));
1863 }
1864 inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, long i)
1865 {
1866 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1867
1868 if (i > 0)
1869 mpz_submul_ui(t.data(), a.data(), static_cast<local_uint_type>(i));
1870 else
1871 mpz_addmul_ui(t.data(), a.data(), static_cast<local_uint_type>(-i));
1872 }
1873 inline void eval_subtract(gmp_int& t, long i)
1874 {
1875 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1876
1877 if (i > 0)
1878 mpz_sub_ui(t.data(), t.data(), static_cast<local_uint_type>(i));
1879 else if (i < 0)
1880 mpz_add_ui(t.data(), t.data(), static_cast<local_uint_type>(-i));
1881 }
1882 inline void eval_multiply(gmp_int& t, long i)
1883 {
1884 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1885
1886 mpz_mul_ui(t.data(), t.data(), static_cast<local_uint_type>(boost::multiprecision::detail::unsigned_abs(i)));
1887
1888 if (i < 0)
1889 mpz_neg(t.data(), t.data());
1890 }
1891 inline void eval_modulus(gmp_int& t, long i)
1892 {
1893 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1894
1895 mpz_tdiv_r_ui(t.data(), t.data(), static_cast<local_uint_type>(boost::multiprecision::detail::unsigned_abs(i)));
1896 }
1897 inline void eval_divide(gmp_int& t, long i)
1898 {
1899 if (i == 0)
1900 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1901
1902 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1903
1904 mpz_tdiv_q_ui(t.data(), t.data(), static_cast<local_uint_type>(boost::multiprecision::detail::unsigned_abs(i)));
1905
1906 if (i < 0)
1907 mpz_neg(t.data(), t.data());
1908 }
1909 template <class UI>
1910 inline void eval_left_shift(gmp_int& t, UI i)
1911 {
1912 mpz_mul_2exp(t.data(), t.data(), static_cast<unsigned long>(i));
1913 }
1914 template <class UI>
1915 inline void eval_right_shift(gmp_int& t, UI i)
1916 {
1917 mpz_fdiv_q_2exp(t.data(), t.data(), static_cast<unsigned long>(i));
1918 }
1919 template <class UI>
1920 inline void eval_left_shift(gmp_int& t, const gmp_int& v, UI i)
1921 {
1922 mpz_mul_2exp(t.data(), v.data(), static_cast<unsigned long>(i));
1923 }
1924 template <class UI>
1925 inline void eval_right_shift(gmp_int& t, const gmp_int& v, UI i)
1926 {
1927 mpz_fdiv_q_2exp(t.data(), v.data(), static_cast<unsigned long>(i));
1928 }
1929
1930 inline void eval_bitwise_and(gmp_int& result, const gmp_int& v)
1931 {
1932 mpz_and(result.data(), result.data(), v.data());
1933 }
1934
1935 inline void eval_bitwise_or(gmp_int& result, const gmp_int& v)
1936 {
1937 mpz_ior(result.data(), result.data(), v.data());
1938 }
1939
1940 inline void eval_bitwise_xor(gmp_int& result, const gmp_int& v)
1941 {
1942 mpz_xor(result.data(), result.data(), v.data());
1943 }
1944
1945 inline void eval_add(gmp_int& t, const gmp_int& p, const gmp_int& o)
1946 {
1947 mpz_add(t.data(), p.data(), o.data());
1948 }
1949 inline void eval_subtract(gmp_int& t, const gmp_int& p, const gmp_int& o)
1950 {
1951 mpz_sub(t.data(), p.data(), o.data());
1952 }
1953 inline void eval_multiply(gmp_int& t, const gmp_int& p, const gmp_int& o)
1954 {
1955 mpz_mul(t.data(), p.data(), o.data());
1956 }
1957 inline void eval_divide(gmp_int& t, const gmp_int& p, const gmp_int& o)
1958 {
1959 if (eval_is_zero(o))
1960 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1961 mpz_tdiv_q(t.data(), p.data(), o.data());
1962 }
1963 inline void eval_modulus(gmp_int& t, const gmp_int& p, const gmp_int& o)
1964 {
1965 mpz_tdiv_r(t.data(), p.data(), o.data());
1966 }
1967 inline void eval_add(gmp_int& t, const gmp_int& p, unsigned long i)
1968 {
1969 mpz_add_ui(t.data(), p.data(), i);
1970 }
1971 inline void eval_subtract(gmp_int& t, const gmp_int& p, unsigned long i)
1972 {
1973 mpz_sub_ui(t.data(), p.data(), i);
1974 }
1975 inline void eval_multiply(gmp_int& t, const gmp_int& p, unsigned long i)
1976 {
1977 mpz_mul_ui(t.data(), p.data(), i);
1978 }
1979 inline void eval_modulus(gmp_int& t, const gmp_int& p, unsigned long i)
1980 {
1981 mpz_tdiv_r_ui(t.data(), p.data(), i);
1982 }
1983 inline void eval_divide(gmp_int& t, const gmp_int& p, unsigned long i)
1984 {
1985 if (i == 0)
1986 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1987 mpz_tdiv_q_ui(t.data(), p.data(), i);
1988 }
1989 inline void eval_add(gmp_int& t, const gmp_int& p, long i)
1990 {
1991 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
1992
1993 if (i > 0)
1994 mpz_add_ui(t.data(), p.data(), static_cast<local_uint_type>(i));
1995 else
1996 mpz_sub_ui(t.data(), p.data(), static_cast<local_uint_type>(-i));
1997 }
1998 inline void eval_subtract(gmp_int& t, const gmp_int& p, long i)
1999 {
2000 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
2001
2002 if (i > 0)
2003 mpz_sub_ui(t.data(), p.data(), static_cast<local_uint_type>(i));
2004 else
2005 mpz_add_ui(t.data(), p.data(), static_cast<local_uint_type>(-i));
2006 }
2007 inline void eval_multiply(gmp_int& t, const gmp_int& p, long i)
2008 {
2009 mpz_mul_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
2010 if (i < 0)
2011 mpz_neg(t.data(), t.data());
2012 }
2013 inline void eval_modulus(gmp_int& t, const gmp_int& p, long i)
2014 {
2015 mpz_tdiv_r_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
2016 }
2017 inline void eval_divide(gmp_int& t, const gmp_int& p, long i)
2018 {
2019 if (i == 0)
2020 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2021 mpz_tdiv_q_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
2022 if (i < 0)
2023 mpz_neg(t.data(), t.data());
2024 }
2025
2026 inline void eval_bitwise_and(gmp_int& result, const gmp_int& u, const gmp_int& v)
2027 {
2028 mpz_and(result.data(), u.data(), v.data());
2029 }
2030
2031 inline void eval_bitwise_or(gmp_int& result, const gmp_int& u, const gmp_int& v)
2032 {
2033 mpz_ior(result.data(), u.data(), v.data());
2034 }
2035
2036 inline void eval_bitwise_xor(gmp_int& result, const gmp_int& u, const gmp_int& v)
2037 {
2038 mpz_xor(result.data(), u.data(), v.data());
2039 }
2040
2041 inline void eval_complement(gmp_int& result, const gmp_int& u)
2042 {
2043 mpz_com(result.data(), u.data());
2044 }
2045
2046 inline int eval_get_sign(const gmp_int& val)
2047 {
2048 return mpz_sgn(val.data());
2049 }
2050 inline void eval_convert_to(unsigned long* result, const gmp_int& val)
2051 {
2052 if (mpz_sgn(val.data()) < 0)
2053 {
2054 BOOST_MP_THROW_EXCEPTION(std::range_error("Conversion from negative integer to an unsigned type results in undefined behaviour"));
2055 }
2056 else
2057 *result = static_cast<unsigned long>(mpz_get_ui(val.data()));
2058 }
2059 inline void eval_convert_to(long* result, const gmp_int& val)
2060 {
2061 if (0 == mpz_fits_slong_p(val.data()))
2062 {
2063 *result = mpz_sgn(val.data()) < 0 ? (std::numeric_limits<long>::min)() : (std::numeric_limits<long>::max)();
2064 }
2065 else
2066 *result = static_cast<long>(mpz_get_si(val.data()));
2067 }
2068 inline void eval_convert_to(long double* result, const gmp_int& val)
2069 {
2070 detail::gmp_char_ptr val_char_ptr {mpz_get_str(nullptr, 10, val.data())};
2071 *result = std::strtold(val_char_ptr.get(), nullptr);
2072 }
2073 inline void eval_convert_to(double* result, const gmp_int& val)
2074 {
2075 *result = mpz_get_d(val.data());
2076 }
2077 #ifdef BOOST_HAS_LONG_LONG
2078 inline void eval_convert_to(unsigned long long* result, const gmp_int& val)
2079 {
2080 if (mpz_sgn(val.data()) < 0)
2081 {
2082 BOOST_MP_THROW_EXCEPTION(std::range_error("Conversion from negative integer to an unsigned type results in undefined behaviour"));
2083 }
2084 *result = 0;
2085 gmp_int t(val);
2086 unsigned parts = sizeof(unsigned long long) / sizeof(unsigned long);
2087
2088 for (unsigned i = 0; i < parts; ++i)
2089 {
2090 unsigned long long part = mpz_get_ui(t.data());
2091 if (i)
2092 *result |= part << (i * sizeof(unsigned long) * CHAR_BIT);
2093 else
2094 *result = part;
2095 mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT);
2096 }
2097 }
2098 inline void eval_convert_to(long long* result, const gmp_int& val)
2099 {
2100 int s = mpz_sgn(val.data());
2101 *result = 0;
2102 gmp_int t(val);
2103 unsigned parts = sizeof(unsigned long long) / sizeof(unsigned long);
2104 unsigned long long unsigned_result = 0;
2105
2106 for (unsigned i = 0; i < parts; ++i)
2107 {
2108 unsigned long long part = mpz_get_ui(t.data());
2109 if (i)
2110 unsigned_result |= part << (i * sizeof(unsigned long) * CHAR_BIT);
2111 else
2112 unsigned_result = part;
2113 mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT);
2114 }
2115
2116
2117
2118 bool overflow = false;
2119 if (mpz_sgn(t.data()))
2120 {
2121 overflow = true;
2122 }
2123 if ((s > 0) && (unsigned_result > static_cast<unsigned long long>((std::numeric_limits<long long>::max)())))
2124 overflow = true;
2125 if((s < 0) && (unsigned_result > 1u - static_cast<unsigned long long>((std::numeric_limits<long long>::min)() + 1)))
2126 overflow = true;
2127 if(overflow)
2128 *result = s < 0 ? (std::numeric_limits<long long>::min)() : (std::numeric_limits<long long>::max)();
2129 else
2130 *result = s < 0 ? -static_cast<long long>(unsigned_result - 1u) - 1 : static_cast<long long>(unsigned_result);
2131 }
2132 #endif
2133 #ifdef BOOST_HAS_INT128
2134 inline void eval_convert_to(uint128_type* result, const gmp_int& val)
2135 {
2136 if (mpz_sgn(val.data()) < 0)
2137 {
2138 BOOST_MP_THROW_EXCEPTION(std::range_error("Conversion from negative integer to an unsigned type results in undefined behaviour"));
2139 }
2140 *result = 0;
2141 gmp_int t(val);
2142 unsigned parts = sizeof(uint128_type) / sizeof(unsigned long);
2143
2144 for (unsigned i = 0; i < parts; ++i)
2145 {
2146 uint128_type part = mpz_get_ui(t.data());
2147 if (i)
2148 *result |= part << (i * sizeof(unsigned long) * CHAR_BIT);
2149 else
2150 *result = part;
2151 mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT);
2152 }
2153 }
2154 inline void eval_convert_to(int128_type* result, const gmp_int& val)
2155 {
2156 int s = mpz_sgn(val.data());
2157 *result = 0;
2158 gmp_int t(val);
2159 unsigned parts = sizeof(uint128_type) / sizeof(unsigned long);
2160 uint128_type unsigned_result = 0;
2161
2162 for (unsigned i = 0; i < parts; ++i)
2163 {
2164 uint128_type part = mpz_get_ui(t.data());
2165 if (i)
2166 unsigned_result |= part << (i * sizeof(unsigned long) * CHAR_BIT);
2167 else
2168 unsigned_result = part;
2169 mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT);
2170 }
2171
2172
2173
2174 constexpr int128_type int128_max = static_cast<int128_type>((static_cast<uint128_type>(1u) << 127) - 1);
2175 constexpr int128_type int128_min = static_cast<int128_type>(static_cast<int128_type>(-int128_max) -1);
2176 bool overflow = false;
2177 if (mpz_sgn(t.data()))
2178 {
2179 overflow = true;
2180 }
2181 if ((s > 0) && (unsigned_result > static_cast<uint128_type>(int128_max)))
2182 overflow = true;
2183 if ((s < 0) && (unsigned_result > 1u - static_cast<uint128_type>(int128_min + 1)))
2184 overflow = true;
2185 if (overflow)
2186 *result = s < 0 ? int128_min : int128_max;
2187 else
2188 *result = s < 0 ? -static_cast<int128_type>(unsigned_result - 1u) - 1 : static_cast<int128_type>(unsigned_result);
2189 }
2190
2191 template <unsigned digits10>
2192 inline void eval_convert_to(int128_type* result, const gmp_float<digits10>& val)
2193 {
2194 gmp_int i;
2195 mpz_set_f(i.data(), val.data());
2196 eval_convert_to(result, i);
2197 }
2198 template <unsigned digits10>
2199 inline void eval_convert_to(uint128_type* result, const gmp_float<digits10>& val)
2200 {
2201 gmp_int i;
2202 mpz_set_f(i.data(), val.data());
2203 eval_convert_to(result, i);
2204 }
2205
2206 #endif
2207
2208 #ifdef BOOST_HAS_FLOAT128
2209 inline void eval_convert_to(float128_type* result, const gmp_int& val)
2210 {
2211 *result = float128_procs::strtoflt128(val.str(0, std::ios_base::fixed).c_str(), nullptr);
2212 }
2213 #endif
2214
2215 inline void eval_abs(gmp_int& result, const gmp_int& val)
2216 {
2217 mpz_abs(result.data(), val.data());
2218 }
2219
2220 inline void eval_gcd(gmp_int& result, const gmp_int& a, const gmp_int& b)
2221 {
2222 mpz_gcd(result.data(), a.data(), b.data());
2223 }
2224 inline void eval_lcm(gmp_int& result, const gmp_int& a, const gmp_int& b)
2225 {
2226 mpz_lcm(result.data(), a.data(), b.data());
2227 }
2228 template <class I>
2229 inline typename std::enable_if<(boost::multiprecision::detail::is_unsigned<I>::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b)
2230 {
2231 mpz_gcd_ui(result.data(), a.data(), b);
2232 }
2233 template <class I>
2234 inline typename std::enable_if<(boost::multiprecision::detail::is_unsigned<I>::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b)
2235 {
2236 mpz_lcm_ui(result.data(), a.data(), b);
2237 }
2238 template <class I>
2239 inline typename std::enable_if<(boost::multiprecision::detail::is_signed<I>::value && boost::multiprecision::detail::is_integral<I>::value && (sizeof(I) <= sizeof(long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b)
2240 {
2241 mpz_gcd_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b));
2242 }
2243 template <class I>
2244 inline typename std::enable_if<boost::multiprecision::detail::is_signed<I>::value && boost::multiprecision::detail::is_integral<I>::value && ((sizeof(I) <= sizeof(long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b)
2245 {
2246 mpz_lcm_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b));
2247 }
2248
2249 inline void eval_integer_sqrt(gmp_int& s, gmp_int& r, const gmp_int& x)
2250 {
2251 mpz_sqrtrem(s.data(), r.data(), x.data());
2252 }
2253
2254 inline std::size_t eval_lsb(const gmp_int& val)
2255 {
2256 int c = eval_get_sign(val);
2257 if (c == 0)
2258 {
2259 BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
2260 }
2261 if (c < 0)
2262 {
2263 BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
2264 }
2265 return static_cast<unsigned>(mpz_scan1(val.data(), 0));
2266 }
2267
2268 inline std::size_t eval_msb(const gmp_int& val)
2269 {
2270 int c = eval_get_sign(val);
2271 if (c == 0)
2272 {
2273 BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
2274 }
2275 if (c < 0)
2276 {
2277 BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
2278 }
2279 return static_cast<unsigned>(mpz_sizeinbase(val.data(), 2) - 1);
2280 }
2281
2282 inline bool eval_bit_test(const gmp_int& val, std::size_t index)
2283 {
2284 return mpz_tstbit(val.data(), index) ? true : false;
2285 }
2286
2287 inline void eval_bit_set(gmp_int& val, std::size_t index)
2288 {
2289 mpz_setbit(val.data(), index);
2290 }
2291
2292 inline void eval_bit_unset(gmp_int& val, std::size_t index)
2293 {
2294 mpz_clrbit(val.data(), index);
2295 }
2296
2297 inline void eval_bit_flip(gmp_int& val, std::size_t index)
2298 {
2299 mpz_combit(val.data(), index);
2300 }
2301
2302 inline void eval_qr(const gmp_int& x, const gmp_int& y,
2303 gmp_int& q, gmp_int& r)
2304 {
2305 mpz_tdiv_qr(q.data(), r.data(), x.data(), y.data());
2306 }
2307
2308 template <class Integer>
2309 inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val)
2310 {
2311 #if defined(__MPIR_VERSION) && (__MPIR_VERSION >= 3)
2312 if ((sizeof(Integer) <= sizeof(mpir_ui)) || (val <= (std::numeric_limits<mpir_ui>::max)()))
2313 #else
2314 if ((sizeof(Integer) <= sizeof(long)) || (val <= (std::numeric_limits<unsigned long>::max)()))
2315 #endif
2316 {
2317 return static_cast<Integer>(mpz_tdiv_ui(x.data(), val));
2318 }
2319 else
2320 {
2321 return default_ops::eval_integer_modulus(x, val);
2322 }
2323 }
2324 template <class Integer>
2325 inline typename std::enable_if<boost::multiprecision::detail::is_signed<Integer>::value && boost::multiprecision::detail::is_integral<Integer>::value, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val)
2326 {
2327 return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val));
2328 }
2329 inline void eval_powm(gmp_int& result, const gmp_int& base, const gmp_int& p, const gmp_int& m)
2330 {
2331 if (eval_get_sign(p) < 0)
2332 {
2333 BOOST_MP_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
2334 }
2335 mpz_powm(result.data(), base.data(), p.data(), m.data());
2336 }
2337
2338 template <class Integer>
2339 inline typename std::enable_if<
2340 boost::multiprecision::detail::is_unsigned<Integer>::value && (sizeof(Integer) <= sizeof(unsigned long))>::type
2341 eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m)
2342 {
2343 mpz_powm_ui(result.data(), base.data(), p, m.data());
2344 }
2345 template <class Integer>
2346 inline typename std::enable_if<boost::multiprecision::detail::is_signed<Integer>::value && boost::multiprecision::detail::is_integral<Integer>::value && (sizeof(Integer) <= sizeof(unsigned long))>::type
2347 eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m)
2348 {
2349 if (p < 0)
2350 {
2351 BOOST_MP_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
2352 }
2353 mpz_powm_ui(result.data(), base.data(), p, m.data());
2354 }
2355
2356 inline std::size_t hash_value(const gmp_int& val)
2357 {
2358
2359 std::size_t result = 0;
2360 for (int i = 0; i < std::abs(val.data()[0]._mp_size); ++i)
2361 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_d[i]);
2362 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_size);
2363 return result;
2364 }
2365
2366 struct gmp_rational;
2367 void eval_add(gmp_rational& t, const gmp_rational& o);
2368
2369 struct gmp_rational
2370 {
2371 #ifdef BOOST_HAS_LONG_LONG
2372 using signed_types = std::tuple<long, long long> ;
2373 using unsigned_types = std::tuple<unsigned long, unsigned long long>;
2374 #else
2375 using signed_types = std::tuple<long> ;
2376 using unsigned_types = std::tuple<unsigned long>;
2377 #endif
2378 using float_types = std::tuple<double, long double>;
2379
2380 gmp_rational()
2381 {
2382 mpq_init(this->m_data);
2383 }
2384 gmp_rational(const gmp_rational& o)
2385 {
2386 mpq_init(m_data);
2387 if (o.m_data[0]._mp_num._mp_d)
2388 mpq_set(m_data, o.m_data);
2389 }
2390 gmp_rational(const gmp_int& o)
2391 {
2392 mpz_init_set(&m_data[0]._mp_num, o.data());
2393 mpz_init_set_ui(&m_data[0]._mp_den, 1u);
2394 }
2395 gmp_rational(long i)
2396 {
2397 mpz_init_set_si(&m_data[0]._mp_num, i);
2398 mpz_init_set_ui(&m_data[0]._mp_den, 1u);
2399 }
2400 gmp_rational(unsigned long ui)
2401 {
2402 mpz_init_set_ui(&m_data[0]._mp_num, ui);
2403 mpz_init_set_ui(&m_data[0]._mp_den, 1u);
2404 }
2405
2406 template <class T, class U>
2407 gmp_rational(const T& a, const U& b, typename std::enable_if<std::is_constructible<gmp_int, T>::value && std::is_constructible<gmp_int, U>::value>::type* = nullptr)
2408 {
2409 gmp_int i(a), j(b);
2410
2411 if (eval_is_zero(j))
2412 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2413
2414 m_data[0]._mp_num = i.data()[0];
2415 m_data[0]._mp_den = j.data()[0];
2416 mpq_canonicalize(m_data);
2417 i.data()[0]._mp_d = nullptr;
2418 j.data()[0]._mp_d = nullptr;
2419 }
2420 template <class U>
2421 gmp_rational(const gmp_int& a, const U& b, typename std::enable_if<std::is_constructible<gmp_int, U>::value>::type* = nullptr)
2422 {
2423 gmp_int j(b);
2424
2425 if (eval_is_zero(j))
2426 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2427
2428 mpz_init_set(&m_data[0]._mp_num, a.data());
2429 m_data[0]._mp_den = j.data()[0];
2430 if (boost::multiprecision::detail::unsigned_abs(b) > 1)
2431 mpq_canonicalize(m_data);
2432 j.data()[0]._mp_d = nullptr;
2433 }
2434 template <class U>
2435 gmp_rational(gmp_int&& a, const U& b, typename std::enable_if<std::is_constructible<gmp_int, U>::value>::type* = nullptr)
2436 {
2437 gmp_int j(b);
2438
2439 if (eval_is_zero(j))
2440 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2441
2442 m_data[0]._mp_num = a.data()[0];
2443 m_data[0]._mp_den = j.data()[0];
2444 if (boost::multiprecision::detail::unsigned_abs(b) > 1)
2445 mpq_canonicalize(m_data);
2446 a.data()[0]._mp_d = nullptr;
2447 j.data()[0]._mp_d = nullptr;
2448 }
2449 template <class T>
2450 gmp_rational(const T& a, const gmp_int& b, typename std::enable_if<std::is_constructible<gmp_int, T>::value>::type* = nullptr)
2451 {
2452 if (eval_is_zero(b))
2453 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2454
2455 gmp_int i(a);
2456 m_data[0]._mp_num = i.data()[0];
2457 mpz_init_set(&m_data[0]._mp_den, b.data());
2458 if(boost::multiprecision::detail::unsigned_abs(a) > 1)
2459 mpq_canonicalize(m_data);
2460 i.data()[0]._mp_d = nullptr;
2461 }
2462 template <class T>
2463 gmp_rational(const T& a, gmp_int&& b, typename std::enable_if<std::is_constructible<gmp_int, T>::value>::type* = nullptr)
2464 {
2465 if (eval_is_zero(static_cast<gmp_int&&>(b)))
2466 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2467
2468 gmp_int i(a);
2469 m_data[0]._mp_num = i.data()[0];
2470 m_data[0]._mp_den = b.data()[0];
2471 if(boost::multiprecision::detail::unsigned_abs(a) > 1)
2472 mpq_canonicalize(m_data);
2473 i.data()[0]._mp_d = nullptr;
2474 b.data()[0]._mp_d = nullptr;
2475 }
2476 gmp_rational(const gmp_int& a, const gmp_int& b)
2477 {
2478 if (eval_is_zero(b))
2479 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2480
2481 mpz_init_set(&m_data[0]._mp_num, a.data());
2482 mpz_init_set(&m_data[0]._mp_den, b.data());
2483 mpq_canonicalize(m_data);
2484 }
2485 gmp_rational(const gmp_int& a, gmp_int&& b)
2486 {
2487 if (eval_is_zero(static_cast<gmp_int&&>(b)))
2488 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2489
2490 mpz_init_set(&m_data[0]._mp_num, a.data());
2491 m_data[0]._mp_den = b.data()[0];
2492 mpq_canonicalize(m_data);
2493 b.data()[0]._mp_d = nullptr;
2494 }
2495 gmp_rational(gmp_int&& a, const gmp_int& b)
2496 {
2497 if (eval_is_zero(b))
2498 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2499
2500 m_data[0]._mp_num = a.data()[0];
2501 mpz_init_set(&m_data[0]._mp_den, b.data());
2502 mpq_canonicalize(m_data);
2503 a.data()[0]._mp_d = nullptr;
2504 }
2505 gmp_rational(gmp_int&& a, gmp_int&& b)
2506 {
2507 if (eval_is_zero(static_cast<gmp_int&&>(b)))
2508 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2509
2510 m_data[0]._mp_num = a.data()[0];
2511 m_data[0]._mp_den = b.data()[0];
2512 mpq_canonicalize(m_data);
2513 a.data()[0]._mp_d = nullptr;
2514 b.data()[0]._mp_d = nullptr;
2515 }
2516
2517 gmp_rational(gmp_rational&& o) noexcept
2518 {
2519 m_data[0] = o.m_data[0];
2520 o.m_data[0]._mp_num._mp_d = nullptr;
2521 o.m_data[0]._mp_den._mp_d = nullptr;
2522 }
2523 gmp_rational(const mpq_t o)
2524 {
2525 mpq_init(m_data);
2526 mpq_set(m_data, o);
2527 }
2528 gmp_rational(const mpz_t o)
2529 {
2530 mpq_init(m_data);
2531 mpq_set_z(m_data, o);
2532 }
2533 gmp_rational& operator=(const gmp_rational& o)
2534 {
2535 if (m_data[0]._mp_den._mp_d == nullptr)
2536 mpq_init(m_data);
2537 mpq_set(m_data, o.m_data);
2538 return *this;
2539 }
2540
2541 gmp_rational& operator=(gmp_rational&& o) noexcept
2542 {
2543 mpq_swap(m_data, o.m_data);
2544 return *this;
2545 }
2546 #ifdef BOOST_HAS_LONG_LONG
2547 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
2548 gmp_rational& operator=(unsigned long long i)
2549 {
2550 *this = static_cast<unsigned long>(i);
2551 return *this;
2552 }
2553 #else
2554 gmp_rational& operator=(unsigned long long i)
2555 {
2556 if (m_data[0]._mp_den._mp_d == nullptr)
2557 mpq_init(m_data);
2558 gmp_int zi;
2559 zi = i;
2560 mpq_set_z(m_data, zi.data());
2561 return *this;
2562 }
2563 gmp_rational& operator=(long long i)
2564 {
2565 if (m_data[0]._mp_den._mp_d == nullptr)
2566 mpq_init(m_data);
2567 bool neg = i < 0;
2568 *this = boost::multiprecision::detail::unsigned_abs(i);
2569 if (neg)
2570 mpq_neg(m_data, m_data);
2571 return *this;
2572 }
2573 #endif
2574 #endif
2575 gmp_rational& operator=(unsigned long i)
2576 {
2577 if (m_data[0]._mp_den._mp_d == nullptr)
2578 mpq_init(m_data);
2579 mpq_set_ui(m_data, i, 1);
2580 return *this;
2581 }
2582 gmp_rational& operator=(long i)
2583 {
2584 if (m_data[0]._mp_den._mp_d == nullptr)
2585 mpq_init(m_data);
2586 mpq_set_si(m_data, i, 1);
2587 return *this;
2588 }
2589 gmp_rational& operator=(double d)
2590 {
2591 if (m_data[0]._mp_den._mp_d == nullptr)
2592 mpq_init(m_data);
2593 mpq_set_d(m_data, d);
2594 return *this;
2595 }
2596 template <class F>
2597 gmp_rational& assign_float(F a)
2598 {
2599 using default_ops::eval_add;
2600 using default_ops::eval_subtract;
2601 BOOST_MP_FLOAT128_USING using std::floor; using std::frexp; using std::ldexp;
2602
2603 if (m_data[0]._mp_den._mp_d == nullptr)
2604 mpq_init(m_data);
2605
2606 if (a == 0)
2607 {
2608 mpq_set_si(m_data, 0, 1);
2609 return *this;
2610 }
2611
2612 if (a == 1)
2613 {
2614 mpq_set_si(m_data, 1, 1);
2615 return *this;
2616 }
2617
2618 BOOST_MP_ASSERT(!BOOST_MP_ISINF(a));
2619 BOOST_MP_ASSERT(!BOOST_MP_ISNAN(a));
2620
2621 int e;
2622 F f, term;
2623 mpq_set_ui(m_data, 0, 1);
2624 mpq_set_ui(m_data, 0u, 1);
2625 gmp_rational t;
2626
2627 f = frexp(a, &e);
2628
2629 constexpr int shift = std::numeric_limits<int>::digits - 1;
2630
2631 while (f != static_cast<F>(0.0f))
2632 {
2633
2634 f = ldexp(f, shift);
2635 term = floor(f);
2636 e -= shift;
2637 mpq_mul_2exp(m_data, m_data, shift);
2638 t = static_cast<long>(term);
2639 eval_add(*this, t);
2640 f -= term;
2641 }
2642 if (e > 0)
2643 mpq_mul_2exp(m_data, m_data, static_cast<mp_bitcnt_t>(e));
2644 else if (e < 0)
2645 mpq_div_2exp(m_data, m_data, static_cast<mp_bitcnt_t>(-e));
2646 return *this;
2647 }
2648 gmp_rational& operator=(long double a)
2649 {
2650 return assign_float(a);
2651 }
2652 #ifdef BOOST_HAS_FLOAT128
2653 gmp_rational& operator=(float128_type a)
2654 {
2655 return assign_float(a);
2656 }
2657 #endif
2658 #ifdef BOOST_HAS_INT128
2659 gmp_rational& operator=(uint128_type i)
2660 {
2661 gmp_int gi;
2662 gi = i;
2663 return *this = gi;
2664 }
2665 gmp_rational& operator=(int128_type i)
2666 {
2667 gmp_int gi;
2668 gi = i;
2669 return *this = gi;
2670 }
2671 #endif
2672 gmp_rational& operator=(const char* s)
2673 {
2674 if (m_data[0]._mp_den._mp_d == nullptr)
2675 mpq_init(m_data);
2676 if (0 != mpq_set_str(m_data, s, 10))
2677 BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid rational number.")));
2678 return *this;
2679 }
2680 gmp_rational& operator=(const gmp_int& o)
2681 {
2682 if (m_data[0]._mp_den._mp_d == nullptr)
2683 mpq_init(m_data);
2684 mpq_set_z(m_data, o.data());
2685 return *this;
2686 }
2687 gmp_rational& operator=(const mpq_t o)
2688 {
2689 if (m_data[0]._mp_den._mp_d == nullptr)
2690 mpq_init(m_data);
2691 mpq_set(m_data, o);
2692 return *this;
2693 }
2694 gmp_rational& operator=(const mpz_t o)
2695 {
2696 if (m_data[0]._mp_den._mp_d == nullptr)
2697 mpq_init(m_data);
2698 mpq_set_z(m_data, o);
2699 return *this;
2700 }
2701 void swap(gmp_rational& o)
2702 {
2703 mpq_swap(m_data, o.m_data);
2704 }
2705 std::string str(std::streamsize , std::ios_base::fmtflags ) const
2706 {
2707 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2708
2709 void* (*alloc_func_ptr)(size_t);
2710 void* (*realloc_func_ptr)(void*, size_t, size_t);
2711 void (*free_func_ptr)(void*, size_t);
2712 const char* ps = mpq_get_str(nullptr, 10, m_data);
2713 std::string s = ps;
2714 mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
2715 (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
2716 return s;
2717 }
2718 ~gmp_rational()
2719 {
2720 if (m_data[0]._mp_num._mp_d || m_data[0]._mp_den._mp_d)
2721 mpq_clear(m_data);
2722 }
2723 void negate()
2724 {
2725 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2726 mpq_neg(m_data, m_data);
2727 }
2728 int compare(const gmp_rational& o) const
2729 {
2730 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d && o.m_data[0]._mp_num._mp_d);
2731 return mpq_cmp(m_data, o.m_data);
2732 }
2733 template <class V>
2734 int compare(V v) const
2735 {
2736 gmp_rational d;
2737 d = v;
2738 return compare(d);
2739 }
2740 int compare(unsigned long v) const
2741 {
2742 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2743 return mpq_cmp_ui(m_data, v, 1);
2744 }
2745 int compare(long v) const
2746 {
2747 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2748 return mpq_cmp_si(m_data, v, 1);
2749 }
2750 mpq_t& data()
2751 {
2752 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2753 return m_data;
2754 }
2755 const mpq_t& data() const
2756 {
2757 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2758 return m_data;
2759 }
2760
2761 protected:
2762 mpq_t m_data;
2763 };
2764
2765 inline bool eval_is_zero(const gmp_rational& val)
2766 {
2767 return mpq_sgn(val.data()) == 0;
2768 }
2769 template <class T>
2770 inline bool eval_eq(gmp_rational& a, const T& b)
2771 {
2772 return a.compare(b) == 0;
2773 }
2774 template <class T>
2775 inline bool eval_lt(gmp_rational& a, const T& b)
2776 {
2777 return a.compare(b) < 0;
2778 }
2779 template <class T>
2780 inline bool eval_gt(gmp_rational& a, const T& b)
2781 {
2782 return a.compare(b) > 0;
2783 }
2784
2785 inline void eval_add(gmp_rational& t, const gmp_rational& o)
2786 {
2787 mpq_add(t.data(), t.data(), o.data());
2788 }
2789 inline void eval_subtract(gmp_rational& t, const gmp_rational& o)
2790 {
2791 mpq_sub(t.data(), t.data(), o.data());
2792 }
2793 inline void eval_multiply(gmp_rational& t, const gmp_rational& o)
2794 {
2795 mpq_mul(t.data(), t.data(), o.data());
2796 }
2797 inline void eval_divide(gmp_rational& t, const gmp_rational& o)
2798 {
2799 if (eval_is_zero(o))
2800 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2801 mpq_div(t.data(), t.data(), o.data());
2802 }
2803 inline void eval_add(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2804 {
2805 mpq_add(t.data(), p.data(), o.data());
2806 }
2807 inline void eval_subtract(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2808 {
2809 mpq_sub(t.data(), p.data(), o.data());
2810 }
2811 inline void eval_multiply(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2812 {
2813 mpq_mul(t.data(), p.data(), o.data());
2814 }
2815 inline void eval_divide(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2816 {
2817 if (eval_is_zero(o))
2818 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2819 mpq_div(t.data(), p.data(), o.data());
2820 }
2821
2822
2823
2824 inline void eval_add(gmp_rational& result, gmp_rational const& a, gmp_int const& b)
2825 {
2826
2827 if (&a != &result)
2828 {
2829 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2830 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2831 }
2832 mpz_addmul(mpq_numref(result.data()), mpq_denref(a.data()), b.data());
2833
2834 }
2835 inline void eval_add(gmp_rational& result, gmp_rational const& a, unsigned long b)
2836 {
2837
2838 if (&a != &result)
2839 {
2840 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2841 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2842 }
2843 mpz_addmul_ui(mpq_numref(result.data()), mpq_denref(a.data()), b);
2844
2845 }
2846 inline void eval_add(gmp_rational& result, gmp_rational const& a, long b)
2847 {
2848
2849 if (&a != &result)
2850 {
2851 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2852 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2853 }
2854
2855 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
2856
2857 if(b > 0)
2858 mpz_addmul_ui(mpq_numref(result.data()), mpq_denref(a.data()), static_cast<local_uint_type>(b));
2859 else
2860 mpz_submul_ui(mpq_numref(result.data()), mpq_denref(a.data()), static_cast<local_uint_type>(-b));
2861
2862 }
2863 template <class T>
2864 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_add(gmp_rational& result, gmp_rational const& a, const T& b)
2865 {
2866 gmp_int t;
2867 t = b;
2868 eval_add(result, a, t);
2869 }
2870 template <class T>
2871 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_add(gmp_rational& result, const T& b, gmp_rational const& a)
2872 {
2873 eval_add(result, a, b);
2874 }
2875 template <class T>
2876 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_add(gmp_rational& result, const T& b)
2877 {
2878 eval_add(result, result, b);
2879 }
2880 inline void eval_subtract(gmp_rational& result, gmp_rational const& a, gmp_int const& b)
2881 {
2882
2883 if (&a != &result)
2884 {
2885 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2886 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2887 }
2888 mpz_submul(mpq_numref(result.data()), mpq_denref(a.data()), b.data());
2889
2890 }
2891 inline void eval_subtract(gmp_rational& result, gmp_rational const& a, unsigned long b)
2892 {
2893
2894 if (&a != &result)
2895 {
2896 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2897 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2898 }
2899 mpz_submul_ui(mpq_numref(result.data()), mpq_denref(a.data()), b);
2900
2901 }
2902 inline void eval_subtract(gmp_rational& result, gmp_rational const& a, long b)
2903 {
2904
2905 if (&a != &result)
2906 {
2907 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2908 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2909 }
2910
2911 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
2912
2913 if(b > 0)
2914 mpz_submul_ui(mpq_numref(result.data()), mpq_denref(a.data()), static_cast<local_uint_type>(b));
2915 else
2916 mpz_addmul_ui(mpq_numref(result.data()), mpq_denref(a.data()), static_cast<local_uint_type>(-b));
2917
2918 }
2919 template <class T>
2920 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_subtract(gmp_rational& result, gmp_rational const& a, const T& b)
2921 {
2922 gmp_int t;
2923 t = b;
2924 eval_subtract(result, a, t);
2925 }
2926 template <class T>
2927 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_subtract(gmp_rational& result, const T& b, gmp_rational const& a)
2928 {
2929 eval_subtract(result, a, b);
2930 result.negate();
2931 }
2932 template <class T>
2933 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_subtract(gmp_rational& result, const T& b)
2934 {
2935 eval_subtract(result, result, b);
2936 }
2937
2938 inline void eval_multiply(gmp_rational& result, gmp_rational const& a, gmp_int const& b)
2939 {
2940 gmp_int g, t;
2941 mpz_gcd(g.data(), mpq_denref(a.data()), b.data());
2942 if (!mpz_fits_uint_p(g.data()) || (mpz_get_ui(g.data()) != 1))
2943 {
2944
2945
2946 eval_divide(t, b, g);
2947 mpz_mul(mpq_numref(result.data()), t.data(), mpq_numref(a.data()));
2948 mpz_divexact(mpq_denref(result.data()), mpq_denref(a.data()), g.data());
2949 }
2950 else
2951 {
2952
2953 mpz_mul(mpq_numref(result.data()), mpq_numref(a.data()), b.data());
2954 if (&result != &a)
2955 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2956 }
2957 }
2958 inline void eval_multiply(gmp_rational& result, gmp_rational const& a, unsigned long b)
2959 {
2960 if (b == 0)
2961 {
2962 mpq_set_ui(result.data(), b, 1);
2963 return;
2964 }
2965 if (mpz_sgn(mpq_numref(a.data())) == 0)
2966 {
2967 result = a;
2968 return;
2969 }
2970 unsigned long g = static_cast<unsigned long>(mpz_gcd_ui(nullptr, mpq_denref(a.data()), b));
2971 if (g != 1)
2972 {
2973 BOOST_MP_ASSERT(g);
2974 b /= g;
2975 mpz_mul_ui(mpq_numref(result.data()), mpq_numref(a.data()), b);
2976 mpz_divexact_ui(mpq_denref(result.data()), mpq_denref(a.data()), g);
2977 }
2978 else
2979 {
2980 mpz_mul_ui(mpq_numref(result.data()), mpq_numref(a.data()), b);
2981 if (&result != &a)
2982 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2983 }
2984 }
2985 inline void eval_multiply(gmp_rational& result, gmp_rational const& a, long b)
2986 {
2987 eval_multiply(result, a, boost::multiprecision::detail::unsigned_abs(b));
2988 if (b < 0)
2989 result.negate();
2990 }
2991 template <class T>
2992 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_multiply(gmp_rational& result, gmp_rational const& a, const T& b)
2993 {
2994 gmp_int t;
2995 t = b;
2996 eval_multiply(result, a, t);
2997 }
2998 template <class T>
2999 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_multiply(gmp_rational& result, const T& b, gmp_rational const& a)
3000 {
3001 eval_multiply(result, a, b);
3002 }
3003 template <class T>
3004 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_multiply(gmp_rational& result, const T& b)
3005 {
3006 eval_multiply(result, result, b);
3007 }
3008
3009 inline int eval_get_sign(const gmp_rational& val)
3010 {
3011 return mpq_sgn(val.data());
3012 }
3013 template <class R>
3014 inline typename std::enable_if<number_category<R>::value == number_kind_floating_point>::type eval_convert_to(R* result, const gmp_rational& backend)
3015 {
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025 ::boost::multiprecision::detail::generic_convert_rational_to_float(*result, backend);
3026 }
3027 #ifdef BOOST_HAS_FLOAT128
3028 inline void eval_convert_to(float128_type* result, const gmp_rational& val)
3029 {
3030 using default_ops::eval_convert_to;
3031
3032 gmp_int n, d;
3033 float128_type fn, fd;
3034 mpz_set(n.data(), mpq_numref(val.data()));
3035 mpz_set(d.data(), mpq_denref(val.data()));
3036
3037 eval_convert_to(&fn, n);
3038 eval_convert_to(&fd, d);
3039
3040 *result = fn / fd;
3041 }
3042 #endif
3043
3044 template <class R>
3045 inline typename std::enable_if<number_category<R>::value == number_kind_integer>::type eval_convert_to(R* result, const gmp_rational& backend)
3046 {
3047 gmp_int n(mpq_numref(backend.data()));
3048 gmp_int d(mpq_denref(backend.data()));
3049 using default_ops::eval_divide;
3050 eval_divide(n, d);
3051 using default_ops::eval_convert_to;
3052 eval_convert_to(result, n);
3053 }
3054
3055 inline void eval_abs(gmp_rational& result, const gmp_rational& val)
3056 {
3057 mpq_abs(result.data(), val.data());
3058 }
3059
3060 inline void assign_components(gmp_rational& result, unsigned long v1, unsigned long v2)
3061 {
3062 if (v2 == 0u)
3063 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
3064
3065 mpq_set_ui(result.data(), v1, v2);
3066 mpq_canonicalize(result.data());
3067 }
3068 inline void assign_components(gmp_rational& result, long v1, long v2)
3069 {
3070 if (v2 == 0)
3071 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
3072
3073 using local_uint_type = typename boost::multiprecision::detail::make_unsigned<long>::type;
3074
3075 if (v2 < 0)
3076 mpq_set_si(result.data(), -v1, static_cast<local_uint_type>(-v2));
3077 else
3078 mpq_set_si(result.data(), v1, static_cast<local_uint_type>(v2));
3079
3080 mpq_canonicalize(result.data());
3081 }
3082 inline void assign_components(gmp_rational& result, gmp_int const& v1, gmp_int const& v2)
3083 {
3084 if (eval_is_zero(v2))
3085 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
3086
3087 mpz_set(mpq_numref(result.data()), v1.data());
3088 mpz_set(mpq_denref(result.data()), v2.data());
3089 mpq_canonicalize(result.data());
3090 }
3091 template <class T, class U>
3092 void assign_components(gmp_rational& result, const T& a, const U& b)
3093 {
3094 gmp_int x, y;
3095
3096 x = a;
3097 y = b;
3098
3099 if (eval_is_zero(y))
3100 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
3101
3102 std::swap(result.data()[0]._mp_num, x.data()[0]);
3103 std::swap(result.data()[0]._mp_den, y.data()[0]);
3104 mpq_canonicalize(result.data());
3105 }
3106 template <class U>
3107 void assign_components(gmp_rational& result, const gmp_int& a, const U& b)
3108 {
3109 gmp_int y;
3110
3111 y = b;
3112
3113 if (eval_is_zero(y))
3114 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
3115
3116 mpz_set(&result.data()[0]._mp_num, a.data());
3117 std::swap(result.data()[0]._mp_den, y.data()[0]);
3118 mpq_canonicalize(result.data());
3119 }
3120 template <class T>
3121 void assign_components(gmp_rational& result, const T& a, const gmp_int& b)
3122 {
3123 if (eval_is_zero(b))
3124 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
3125
3126 gmp_int x;
3127 x = a;
3128 std::swap(result.data()[0]._mp_num, x.data()[0]);
3129 mpz_set(&result.data()[0]._mp_den, b.data());
3130 mpq_canonicalize(result.data());
3131 }
3132
3133
3134 inline std::size_t hash_value(const gmp_rational& val)
3135 {
3136 std::size_t result = 0;
3137 for (int i = 0; i < std::abs(val.data()[0]._mp_num._mp_size); ++i)
3138 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_num._mp_d[i]);
3139 for (int i = 0; i < std::abs(val.data()[0]._mp_den._mp_size); ++i)
3140 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_den._mp_d[i]);
3141 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_num._mp_size);
3142 return result;
3143 }
3144
3145
3146
3147
3148 inline std::size_t used_gmp_int_bits(const gmp_int& val)
3149 {
3150 return eval_msb(val) - eval_lsb(val) + 1;
3151 }
3152 inline std::size_t used_gmp_rational_bits(const gmp_rational& val)
3153 {
3154 unsigned d2_d = static_cast<unsigned>(mpz_sizeinbase(mpq_denref(val.data()), 2) - mpz_scan1(mpq_denref(val.data()), 0));
3155 unsigned d2_n = static_cast<unsigned>(mpz_sizeinbase(mpq_numref(val.data()), 2) - mpz_scan1(mpq_numref(val.data()), 0));
3156 return (std::max)(d2_d, d2_n);
3157 }
3158
3159
3160
3161
3162 template <unsigned Digits10>
3163 template <unsigned D>
3164 inline gmp_float<Digits10>::gmp_float(const gmp_float<D>& o, typename std::enable_if<D <= Digits10>::type*)
3165 {
3166 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3167 mpf_set(this->m_data, o.data());
3168 }
3169 template <unsigned Digits10>
3170 template <unsigned D>
3171 inline gmp_float<Digits10>::gmp_float(const gmp_float<D>& o, typename std::enable_if< !(D <= Digits10)>::type*)
3172 {
3173 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3174 mpf_set(this->m_data, o.data());
3175 }
3176 template <unsigned Digits10>
3177 inline gmp_float<Digits10>::gmp_float(const gmp_int& o)
3178 {
3179 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3180 mpf_set_z(this->data(), o.data());
3181 }
3182 template <unsigned Digits10>
3183 inline gmp_float<Digits10>::gmp_float(const gmp_rational& o)
3184 {
3185 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3186 mpf_set_q(this->data(), o.data());
3187 }
3188 template <unsigned Digits10>
3189 template <unsigned D>
3190 inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_float<D>& o)
3191 {
3192 if (this->m_data[0]._mp_d == nullptr)
3193 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3194 mpf_set(this->m_data, o.data());
3195 return *this;
3196 }
3197 template <unsigned Digits10>
3198 inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_int& o)
3199 {
3200 if (this->m_data[0]._mp_d == nullptr)
3201 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3202 mpf_set_z(this->data(), o.data());
3203 return *this;
3204 }
3205 template <unsigned Digits10>
3206 inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_rational& o)
3207 {
3208 if (this->m_data[0]._mp_d == nullptr)
3209 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3210 mpf_set_q(this->data(), o.data());
3211 return *this;
3212 }
3213 inline gmp_float<0>::gmp_float(const gmp_int& o) : requested_precision(get_default_precision())
3214 {
3215 if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3216 {
3217 std::size_t d2 = used_gmp_int_bits(o);
3218 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(d2);
3219 if (d10 > requested_precision)
3220 requested_precision = static_cast<unsigned>(d10);
3221 }
3222 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
3223 mpf_set_z(this->data(), o.data());
3224 }
3225 inline gmp_float<0>::gmp_float(const gmp_rational& o) : requested_precision(get_default_precision())
3226 {
3227 if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3228 {
3229 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(o));
3230 if (d10 > requested_precision)
3231 requested_precision = static_cast<unsigned>(d10);
3232 }
3233 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
3234 mpf_set_q(this->data(), o.data());
3235 }
3236 inline gmp_float<0>& gmp_float<0>::operator=(const gmp_int& o)
3237 {
3238 if (this->m_data[0]._mp_d == nullptr)
3239 {
3240 requested_precision = this->get_default_precision();
3241 if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3242 {
3243 std::size_t d2 = used_gmp_int_bits(o);
3244 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(d2);
3245 if (d10 > requested_precision)
3246 requested_precision = static_cast<unsigned>(d10);
3247 }
3248 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
3249 }
3250 else if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3251 {
3252 std::size_t d2 = used_gmp_int_bits(o);
3253 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(d2);
3254 if (d10 > requested_precision)
3255 this->precision(static_cast<unsigned>(d10));
3256 }
3257 mpf_set_z(this->data(), o.data());
3258 return *this;
3259 }
3260 inline gmp_float<0>& gmp_float<0>::operator=(const gmp_rational& o)
3261 {
3262 if (this->m_data[0]._mp_d == nullptr)
3263 {
3264 requested_precision = this->get_default_precision();
3265 if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3266 {
3267 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(o));
3268 if (d10 > requested_precision)
3269 requested_precision = static_cast<unsigned>(d10);
3270 }
3271 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
3272 }
3273 else if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3274 {
3275 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(o));
3276 if (d10 > requested_precision)
3277 this->precision(static_cast<unsigned>(d10));
3278 }
3279 mpf_set_q(this->data(), o.data());
3280 return *this;
3281 }
3282 inline gmp_int::gmp_int(const gmp_rational& o)
3283 {
3284 mpz_init(this->m_data);
3285 mpz_set_q(this->m_data, o.data());
3286 }
3287 inline gmp_int& gmp_int::operator=(const gmp_rational& o)
3288 {
3289 if (this->m_data[0]._mp_d == nullptr)
3290 mpz_init(this->m_data);
3291 mpz_set_q(this->m_data, o.data());
3292 return *this;
3293 }
3294
3295 }
3296
3297 template <expression_template_option ExpressionTemplates>
3298 struct component_type<number<gmp_rational, ExpressionTemplates> >
3299 {
3300 using type = number<gmp_int, ExpressionTemplates>;
3301 };
3302
3303 template <expression_template_option ET>
3304 inline number<gmp_int, ET> numerator(const number<gmp_rational, ET>& val)
3305 {
3306 number<gmp_int, ET> result;
3307 mpz_set(result.backend().data(), (mpq_numref(val.backend().data())));
3308 return result;
3309 }
3310 template <expression_template_option ET>
3311 inline number<gmp_int, ET> denominator(const number<gmp_rational, ET>& val)
3312 {
3313 number<gmp_int, ET> result;
3314 mpz_set(result.backend().data(), (mpq_denref(val.backend().data())));
3315 return result;
3316 }
3317
3318 namespace detail {
3319
3320 template <>
3321 struct digits2<number<gmp_float<0>, et_on> >
3322 {
3323 static long value()
3324 {
3325 return static_cast<long>(multiprecision::detail::digits10_2_2(gmp_float<0>::thread_default_precision()));
3326 }
3327 };
3328
3329 template <>
3330 struct digits2<number<gmp_float<0>, et_off> >
3331 {
3332 static long value()
3333 {
3334 return static_cast<long>(multiprecision::detail::digits10_2_2(gmp_float<0>::thread_default_precision()));
3335 }
3336 };
3337
3338 template <>
3339 struct digits2<number<debug_adaptor<gmp_float<0> >, et_on> >
3340 {
3341 static long value()
3342 {
3343 return static_cast<long>(multiprecision::detail::digits10_2_2(gmp_float<0>::thread_default_precision()));
3344 }
3345 };
3346
3347 template <>
3348 struct digits2<number<debug_adaptor<gmp_float<0> >, et_off> >
3349 {
3350 static long value()
3351 {
3352 return static_cast<long>(multiprecision::detail::digits10_2_2(gmp_float<0>::thread_default_precision()));
3353 }
3354 };
3355
3356 template <unsigned Digits10>
3357 struct transcendental_reduction_type<boost::multiprecision::backends::gmp_float<Digits10> >
3358 {
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368 using type = boost::multiprecision::backends::gmp_float<Digits10 * 3>;
3369 };
3370
3371
3372 }
3373
3374 template <>
3375 struct number_category<detail::canonical<mpz_t, gmp_int>::type> : public std::integral_constant<int, number_kind_integer>
3376 {};
3377 template <>
3378 struct number_category<detail::canonical<mpq_t, gmp_rational>::type> : public std::integral_constant<int, number_kind_rational>
3379 {};
3380 template <>
3381 struct number_category<detail::canonical<mpf_t, gmp_float<0> >::type> : public std::integral_constant<int, number_kind_floating_point>
3382 {};
3383
3384 namespace detail {
3385 template <>
3386 struct is_variable_precision<backends::gmp_float<0> > : public std::integral_constant<bool, true>
3387 {};
3388 }
3389
3390 }
3391
3392 namespace math { namespace tools {
3393
3394 #ifndef BOOST_MP_MATH_AVAILABLE
3395
3396 template <typename T>
3397 inline int digits();
3398
3399 template <typename T>
3400 inline T max_value();
3401
3402 template <typename T>
3403 inline T min_value();
3404
3405 #endif
3406
3407 inline void set_output_precision(const boost::multiprecision::mpf_float& val, std::ostream& os)
3408 {
3409 const int sz_prec = static_cast<int>(val.precision());
3410
3411 os << std::setprecision(sz_prec);
3412 }
3413
3414 template <>
3415 inline int digits<boost::multiprecision::mpf_float>()
3416 #ifdef BOOST_MATH_NOEXCEPT
3417 noexcept
3418 #endif
3419 {
3420 return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::thread_default_precision()));
3421 }
3422 template <>
3423 inline int digits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
3424 #ifdef BOOST_MATH_NOEXCEPT
3425 noexcept
3426 #endif
3427 {
3428 return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::thread_default_precision()));
3429 }
3430
3431 template <>
3432 inline boost::multiprecision::mpf_float
3433 max_value<boost::multiprecision::mpf_float>()
3434 {
3435 boost::multiprecision::mpf_float result(0.5);
3436 mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3437 return result;
3438 }
3439
3440 template <>
3441 inline boost::multiprecision::mpf_float
3442 min_value<boost::multiprecision::mpf_float>()
3443 {
3444 boost::multiprecision::mpf_float result(0.5);
3445 mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3446 return result;
3447 }
3448
3449 template <>
3450 inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off>
3451 max_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
3452 {
3453 boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5);
3454 mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3455 return result;
3456 }
3457
3458 template <>
3459 inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off>
3460 min_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
3461 {
3462 boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5);
3463 mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3464 return result;
3465 }
3466
3467 template <>
3468 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
3469 #ifdef BOOST_MATH_NOEXCEPT
3470 noexcept
3471 #endif
3472 {
3473 return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::thread_default_precision()));
3474 }
3475 template <>
3476 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
3477 #ifdef BOOST_MATH_NOEXCEPT
3478 noexcept
3479 #endif
3480 {
3481 return static_cast<int>(multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::thread_default_precision()));
3482 }
3483
3484 template <>
3485 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >
3486 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
3487 {
3488 return max_value<boost::multiprecision::mpf_float>().backend();
3489 }
3490
3491 template <>
3492 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >
3493 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
3494 {
3495 return min_value<boost::multiprecision::mpf_float>().backend();
3496 }
3497
3498 template <>
3499 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off>
3500 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
3501 {
3502 return max_value<boost::multiprecision::mpf_float>().backend();
3503 }
3504
3505 template <>
3506 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off>
3507 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
3508 {
3509 return min_value<boost::multiprecision::mpf_float>().backend();
3510 }
3511
3512 }}
3513
3514 }
3515
3516 namespace std {
3517
3518
3519
3520
3521 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3522 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >
3523 {
3524 using number_type = boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates>;
3525
3526
3527
3528
3529
3530
3531 static number_type calc_min()
3532 {
3533 number_type result(1);
3534 mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3535 return result;
3536 }
3537 static number_type calc_max()
3538 {
3539 number_type result(1);
3540 mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3541 return result;
3542 }
3543 static number_type calc_epsilon()
3544 {
3545 number_type result(1);
3546 mpf_div_2exp(result.backend().data(), result.backend().data(), std::numeric_limits<number_type>::digits - 1);
3547 return result;
3548 }
3549
3550
3551 public:
3552 static constexpr bool is_specialized = true;
3553 static number_type(min)()
3554 {
3555
3556 static const number_type value{calc_min()};
3557 return value;
3558 }
3559 static number_type(max)()
3560 {
3561 static number_type value{calc_max()};
3562 return value;
3563 }
3564 static constexpr number_type lowest()
3565 {
3566 return -(max)();
3567 }
3568 static constexpr int digits = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301L ? 2 : 1));
3569 static constexpr int digits10 = Digits10;
3570
3571 static constexpr int max_digits10 = Digits10 + 3 + ((GMP_LIMB_BITS * 301L) / 1000L);
3572 static constexpr bool is_signed = true;
3573 static constexpr bool is_integer = false;
3574 static constexpr bool is_exact = false;
3575 static constexpr int radix = 2;
3576 static number_type epsilon()
3577 {
3578 static const number_type value{calc_epsilon()};
3579 return value;
3580 }
3581
3582 static number_type round_error()
3583 {
3584 return 1;
3585 }
3586 static constexpr long min_exponent = LONG_MIN;
3587 static constexpr long min_exponent10 = (LONG_MIN / 1000) * 301L;
3588 static constexpr long max_exponent = LONG_MAX;
3589 static constexpr long max_exponent10 = (LONG_MAX / 1000) * 301L;
3590 static constexpr bool has_infinity = false;
3591 static constexpr bool has_quiet_NaN = false;
3592 static constexpr bool has_signaling_NaN = false;
3593 static constexpr float_denorm_style has_denorm = denorm_absent;
3594 static constexpr bool has_denorm_loss = false;
3595 static constexpr number_type infinity() { return number_type(); }
3596 static constexpr number_type quiet_NaN() { return number_type(); }
3597 static constexpr number_type signaling_NaN() { return number_type(); }
3598 static constexpr number_type denorm_min() { return (min)(); }
3599 static constexpr bool is_iec559 = false;
3600 static constexpr bool is_bounded = true;
3601 static constexpr bool is_modulo = false;
3602 static constexpr bool traps = true;
3603 static constexpr bool tinyness_before = false;
3604 static constexpr float_round_style round_style = round_indeterminate;
3605 };
3606
3607 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3608 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::digits;
3609 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3610 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::digits10;
3611 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3612 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_digits10;
3613 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3614 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_signed;
3615 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3616 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_integer;
3617 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3618 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_exact;
3619 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3620 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::radix;
3621 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3622 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::min_exponent;
3623 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3624 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::min_exponent10;
3625 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3626 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_exponent;
3627 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3628 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_exponent10;
3629 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3630 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_infinity;
3631 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3632 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_quiet_NaN;
3633 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3634 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_signaling_NaN;
3635 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3636 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_denorm;
3637 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3638 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_denorm_loss;
3639 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3640 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_iec559;
3641 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3642 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_bounded;
3643 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3644 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_modulo;
3645 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3646 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::traps;
3647 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3648 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::tinyness_before;
3649 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3650 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::round_style;
3651
3652 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3653 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >
3654 {
3655 using number_type = boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates>;
3656
3657 public:
3658 static constexpr bool is_specialized = false;
3659 static number_type(min)() { return number_type(); }
3660 static number_type(max)() { return number_type(); }
3661 static number_type lowest() { return number_type(); }
3662 static constexpr int digits = 0;
3663 static constexpr int digits10 = 0;
3664 static constexpr int max_digits10 = 0;
3665 static constexpr bool is_signed = false;
3666 static constexpr bool is_integer = false;
3667 static constexpr bool is_exact = false;
3668 static constexpr int radix = 0;
3669 static number_type epsilon() { return number_type(); }
3670 static number_type round_error() { return number_type(); }
3671 static constexpr int min_exponent = 0;
3672 static constexpr int min_exponent10 = 0;
3673 static constexpr int max_exponent = 0;
3674 static constexpr int max_exponent10 = 0;
3675 static constexpr bool has_infinity = false;
3676 static constexpr bool has_quiet_NaN = false;
3677 static constexpr bool has_signaling_NaN = false;
3678 static constexpr float_denorm_style has_denorm = denorm_absent;
3679 static constexpr bool has_denorm_loss = false;
3680 static number_type infinity() { return number_type(); }
3681 static number_type quiet_NaN() { return number_type(); }
3682 static number_type signaling_NaN() { return number_type(); }
3683 static number_type denorm_min() { return number_type(); }
3684 static constexpr bool is_iec559 = false;
3685 static constexpr bool is_bounded = false;
3686 static constexpr bool is_modulo = false;
3687 static constexpr bool traps = false;
3688 static constexpr bool tinyness_before = false;
3689 static constexpr float_round_style round_style = round_indeterminate;
3690 };
3691
3692 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3693 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits;
3694 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3695 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits10;
3696 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3697 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_digits10;
3698 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3699 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_signed;
3700 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3701 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_integer;
3702 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3703 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_exact;
3704 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3705 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::radix;
3706 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3707 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent;
3708 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3709 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent10;
3710 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3711 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent;
3712 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3713 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent10;
3714 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3715 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_infinity;
3716 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3717 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_quiet_NaN;
3718 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3719 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_signaling_NaN;
3720 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3721 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm;
3722 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3723 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm_loss;
3724 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3725 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_iec559;
3726 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3727 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_bounded;
3728 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3729 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_modulo;
3730 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3731 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::traps;
3732 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3733 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::tinyness_before;
3734 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3735 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::round_style;
3736
3737 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3738 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >
3739 {
3740 using number_type = boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates>;
3741
3742 public:
3743 static constexpr bool is_specialized = true;
3744
3745
3746
3747
3748 static number_type(min)()
3749 {
3750 return number_type();
3751 }
3752 static number_type(max)()
3753 {
3754 return number_type();
3755 }
3756 static number_type lowest() { return (min)(); }
3757 static constexpr int digits = INT_MAX;
3758 static constexpr int digits10 = (INT_MAX / 1000) * 301L;
3759 static constexpr int max_digits10 = digits10 + 3;
3760 static constexpr bool is_signed = true;
3761 static constexpr bool is_integer = true;
3762 static constexpr bool is_exact = true;
3763 static constexpr int radix = 2;
3764 static number_type epsilon() { return number_type(); }
3765 static number_type round_error() { return number_type(); }
3766 static constexpr int min_exponent = 0;
3767 static constexpr int min_exponent10 = 0;
3768 static constexpr int max_exponent = 0;
3769 static constexpr int max_exponent10 = 0;
3770 static constexpr bool has_infinity = false;
3771 static constexpr bool has_quiet_NaN = false;
3772 static constexpr bool has_signaling_NaN = false;
3773 static constexpr float_denorm_style has_denorm = denorm_absent;
3774 static constexpr bool has_denorm_loss = false;
3775 static number_type infinity() { return number_type(); }
3776 static number_type quiet_NaN() { return number_type(); }
3777 static number_type signaling_NaN() { return number_type(); }
3778 static number_type denorm_min() { return number_type(); }
3779 static constexpr bool is_iec559 = false;
3780 static constexpr bool is_bounded = false;
3781 static constexpr bool is_modulo = false;
3782 static constexpr bool traps = false;
3783 static constexpr bool tinyness_before = false;
3784 static constexpr float_round_style round_style = round_toward_zero;
3785 };
3786
3787 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3788 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits;
3789 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3790 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits10;
3791 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3792 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_digits10;
3793 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3794 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_signed;
3795 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3796 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_integer;
3797 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3798 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_exact;
3799 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3800 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::radix;
3801 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3802 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent;
3803 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3804 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent10;
3805 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3806 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent;
3807 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3808 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent10;
3809 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3810 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_infinity;
3811 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3812 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_quiet_NaN;
3813 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3814 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_signaling_NaN;
3815 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3816 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm;
3817 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3818 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm_loss;
3819 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3820 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_iec559;
3821 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3822 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_bounded;
3823 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3824 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_modulo;
3825 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3826 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::traps;
3827 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3828 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::tinyness_before;
3829 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3830 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::round_style;
3831
3832 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3833 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >
3834 {
3835 using number_type = boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates>;
3836
3837 public:
3838 static constexpr bool is_specialized = true;
3839
3840
3841
3842
3843 static number_type(min)()
3844 {
3845 return number_type();
3846 }
3847 static number_type(max)()
3848 {
3849 return number_type();
3850 }
3851 static number_type lowest() { return (min)(); }
3852
3853 static constexpr int digits = INT_MAX;
3854 static constexpr int digits10 = (INT_MAX / 1000) * 301L;
3855 static constexpr int max_digits10 = digits10 + 3;
3856 static constexpr bool is_signed = true;
3857 static constexpr bool is_integer = false;
3858 static constexpr bool is_exact = true;
3859 static constexpr int radix = 2;
3860 static number_type epsilon() { return number_type(); }
3861 static number_type round_error() { return number_type(); }
3862 static constexpr int min_exponent = 0;
3863 static constexpr int min_exponent10 = 0;
3864 static constexpr int max_exponent = 0;
3865 static constexpr int max_exponent10 = 0;
3866 static constexpr bool has_infinity = false;
3867 static constexpr bool has_quiet_NaN = false;
3868 static constexpr bool has_signaling_NaN = false;
3869 static constexpr float_denorm_style has_denorm = denorm_absent;
3870 static constexpr bool has_denorm_loss = false;
3871 static number_type infinity() { return number_type(); }
3872 static number_type quiet_NaN() { return number_type(); }
3873 static number_type signaling_NaN() { return number_type(); }
3874 static number_type denorm_min() { return (min)(); }
3875 static constexpr bool is_iec559 = false;
3876 static constexpr bool is_bounded = false;
3877 static constexpr bool is_modulo = false;
3878 static constexpr bool traps = false;
3879 static constexpr bool tinyness_before = false;
3880 static constexpr float_round_style round_style = round_toward_zero;
3881 };
3882
3883 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3884 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits;
3885 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3886 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits10;
3887 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3888 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_digits10;
3889 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3890 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_signed;
3891 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3892 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_integer;
3893 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3894 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_exact;
3895 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3896 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::radix;
3897 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3898 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent;
3899 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3900 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent10;
3901 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3902 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent;
3903 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3904 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent10;
3905 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3906 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_infinity;
3907 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3908 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_quiet_NaN;
3909 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3910 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_signaling_NaN;
3911 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3912 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm;
3913 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3914 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm_loss;
3915 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3916 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_iec559;
3917 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3918 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_bounded;
3919 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3920 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_modulo;
3921 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3922 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::traps;
3923 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3924 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::tinyness_before;
3925 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3926 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::round_style;
3927
3928 #ifdef BOOST_MSVC
3929 #pragma warning(pop)
3930 #endif
3931
3932 }
3933
3934 namespace Eigen
3935 {
3936
3937 template <class B1, class B2>
3938 struct NumTraitsImp;
3939
3940 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3941 struct NumTraitsImp<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates>, boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >
3942 {
3943 using self_type = boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates>;
3944 using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
3945 using NonInteger = self_type;
3946 using Literal = double;
3947 using Nested = self_type;
3948 enum
3949 {
3950 IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
3951 IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
3952 ReadCost = 1,
3953 AddCost = 4,
3954 MulCost = 8,
3955 IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
3956 RequireInitialization = 1,
3957 };
3958
3959 static Real highest() noexcept
3960 {
3961 return boost::math::tools::max_value<Real>();
3962 }
3963 static Real lowest() noexcept
3964 {
3965 return boost::math::tools::min_value<Real>();
3966 }
3967 static int digits() noexcept
3968 {
3969 return boost::math::tools::digits<Real>();
3970 }
3971 static int digits10()
3972 {
3973 return Real::thread_default_precision();
3974 }
3975 static Real epsilon()
3976 {
3977 return ldexp(Real(1), 1 - digits());
3978 }
3979 static Real dummy_precision()
3980 {
3981 return 1000 * epsilon();
3982 }
3983 static constexpr long min_exponent() noexcept
3984 {
3985 return LONG_MIN;
3986 }
3987 static constexpr long max_exponent() noexcept
3988 {
3989 return LONG_MAX;
3990 }
3991 static Real infinity()
3992 {
3993 return Real();
3994 }
3995 static Real quiet_NaN()
3996 {
3997 return Real();
3998 }
3999 };
4000
4001 }
4002
4003
4004 #endif