1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright 2011 John Maddock.
3 // Copyright 2021 Matt Borland. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 #ifndef BOOST_MATH_ER_GMP_BACKEND_HPP
8 #define BOOST_MATH_ER_GMP_BACKEND_HPP
10 #include <boost/multiprecision/detail/standalone_config.hpp>
11 #include <boost/multiprecision/number.hpp>
12 #include <boost/multiprecision/debug_adaptor.hpp>
13 #include <boost/multiprecision/detail/integer_ops.hpp>
14 #include <boost/multiprecision/detail/float128_functions.hpp>
15 #include <boost/multiprecision/detail/digits.hpp>
16 #include <boost/multiprecision/detail/atomic.hpp>
17 #include <boost/multiprecision/detail/hash.hpp>
18 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
19 #include <boost/multiprecision/detail/assert.hpp>
20 #include <boost/multiprecision/detail/fpclassify.hpp>
21 #include <type_traits>
33 // Some includes we need from Boost.Math, since we rely on that library to provide these functions:
35 #ifdef BOOST_MP_MATH_AVAILABLE
36 #include <boost/math/special_functions/asinh.hpp>
37 #include <boost/math/special_functions/acosh.hpp>
38 #include <boost/math/special_functions/atanh.hpp>
39 #include <boost/math/special_functions/cbrt.hpp>
40 #include <boost/math/special_functions/expm1.hpp>
41 #include <boost/math/special_functions/gamma.hpp>
46 #pragma warning(disable : 4127)
53 #if defined(__MPIR_VERSION) && defined(__MPIR_VERSION_MINOR) && defined(__MPIR_VERSION_PATCHLEVEL)
54 #define BOOST_MP_MPIR_VERSION (__MPIR_VERSION * 10000 + __MPIR_VERSION_MINOR * 100 + __MPIR_VERSION_PATCHLEVEL)
56 #define BOOST_MP_MPIR_VERSION 0
60 namespace multiprecision {
64 // warning C4127: conditional expression is constant
66 //#pragma warning(disable : 4127)
69 template <unsigned digits10>
74 } // namespace backends
77 struct number_category<backends::gmp_int> : public std::integral_constant<int, number_kind_integer>
80 struct number_category<backends::gmp_rational> : public std::integral_constant<int, number_kind_rational>
82 template <unsigned digits10>
83 struct number_category<backends::gmp_float<digits10> > : public std::integral_constant<int, number_kind_floating_point>
88 // Within this file, the only functions we mark as noexcept are those that manipulate
89 // (but don't create) an mpf_t. All other types may allocate at pretty much any time
90 // via a user-supplied allocator, and therefore throw.
94 template <unsigned digits10>
97 #ifdef BOOST_HAS_LONG_LONG
98 using signed_types = std::tuple<long, long long> ;
99 using unsigned_types = std::tuple<unsigned long, unsigned long long>;
101 using signed_types = std::tuple<long> ;
102 using unsigned_types = std::tuple<unsigned long>;
104 using float_types = std::tuple<double, long double>;
105 using exponent_type = long ;
107 gmp_float_imp() noexcept
109 m_data[0]._mp_d = 0; // uninitialized m_data
110 m_data[0]._mp_prec = 1;
113 gmp_float_imp(const gmp_float_imp& o)
116 // We have to do an init followed by a set here, otherwise *this may be at
117 // a lower precision than o: seems like mpf_init_set copies just enough bits
118 // to get the right value, but if it's then used in further calculations
119 // things go badly wrong!!
121 mpf_init2(m_data, preserve_source_precision() ? mpf_get_prec(o.data()) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
122 if (o.m_data[0]._mp_d)
123 mpf_set(m_data, o.m_data);
126 gmp_float_imp(gmp_float_imp&& o) noexcept
128 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())))
130 mpf_init2(m_data, boost::multiprecision::detail::digits10_2_2(get_default_precision()));
131 *this = static_cast<const gmp_float_imp&>(o);
135 m_data[0] = o.m_data[0];
136 o.m_data[0]._mp_d = 0;
140 gmp_float_imp& operator=(const gmp_float_imp& o)
142 if (m_data[0]._mp_d == 0)
144 mpf_init2(m_data, preserve_source_precision() ? mpf_get_prec(o.data()) : boost::multiprecision::detail::digits10_2_2(get_default_precision()));
145 mpf_set(m_data, o.m_data);
147 else if (preserve_source_precision() && (mpf_get_prec(data()) != mpf_get_prec(o.data())))
150 mpf_init2(t, mpf_get_prec(o.data()));
151 mpf_set(t, o.data());
157 mpf_set(m_data, o.m_data);
162 gmp_float_imp& operator=(gmp_float_imp&& o) noexcept
164 if ((this->get_default_options() == variable_precision_options::preserve_target_precision) && (mpf_get_prec(o.data()) != mpf_get_prec(data())))
165 *this = static_cast<const gmp_float_imp&>(o);
168 mpf_swap(m_data, o.m_data);
173 #ifdef BOOST_HAS_LONG_LONG
174 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
175 gmp_float_imp& operator=(unsigned long long i)
177 *this = static_cast<unsigned long>(i);
181 gmp_float_imp& operator=(unsigned long long i)
183 if (m_data[0]._mp_d == 0)
185 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
187 unsigned long long mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
190 mpf_init2(t, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
191 mpf_set_ui(m_data, 0);
194 mpf_set_ui(t, static_cast<unsigned long>(i & mask));
196 mpf_mul_2exp(t, t, shift);
197 mpf_add(m_data, m_data, t);
198 shift += std::numeric_limits<unsigned long>::digits;
199 i >>= std::numeric_limits<unsigned long>::digits;
205 gmp_float_imp& operator=(long long i)
207 if (m_data[0]._mp_d == 0)
209 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
212 *this = static_cast<unsigned long long>(boost::multiprecision::detail::unsigned_abs(i));
214 mpf_neg(m_data, m_data);
218 gmp_float_imp& operator=(unsigned long i)
220 if (m_data[0]._mp_d == 0)
222 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
224 mpf_set_ui(m_data, i);
227 gmp_float_imp& operator=(long i)
229 if (m_data[0]._mp_d == 0)
231 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
233 mpf_set_si(m_data, i);
236 #ifdef BOOST_HAS_INT128
237 gmp_float_imp& operator=(uint128_type i)
239 if (m_data[0]._mp_d == 0)
241 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
243 unsigned long mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
246 mpf_init2(t, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
247 mpf_set_ui(m_data, 0);
250 mpf_set_ui(t, static_cast<unsigned long>(i & mask));
252 mpf_mul_2exp(t, t, shift);
253 mpf_add(m_data, m_data, t);
254 shift += std::numeric_limits<unsigned long>::digits;
255 i >>= std::numeric_limits<unsigned long>::digits;
260 gmp_float_imp& operator=(int128_type i)
262 if (m_data[0]._mp_d == 0)
264 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
267 *this = static_cast<uint128_type>(boost::multiprecision::detail::unsigned_abs(i));
269 mpf_neg(m_data, m_data);
273 gmp_float_imp& operator=(double d)
275 if (m_data[0]._mp_d == 0)
277 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
279 mpf_set_d(m_data, d);
283 gmp_float_imp& assign_float(F a)
285 BOOST_MP_FLOAT128_USING using std::floor; using std::frexp; using std::ldexp;
287 if (m_data[0]._mp_d == 0)
289 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
294 mpf_set_si(m_data, 0);
300 mpf_set_si(m_data, 1);
304 BOOST_MP_ASSERT(!BOOST_MP_ISINF(a));
305 BOOST_MP_ASSERT(!BOOST_MP_ISNAN(a));
309 mpf_set_ui(m_data, 0u);
313 constexpr const int shift = std::numeric_limits<int>::digits - 1;
317 // extract int sized bits from f:
321 mpf_mul_2exp(m_data, m_data, shift);
323 mpf_add_ui(m_data, m_data, static_cast<unsigned>(term));
325 mpf_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
329 mpf_mul_2exp(m_data, m_data, e);
331 mpf_div_2exp(m_data, m_data, -e);
334 gmp_float_imp& operator=(long double a)
336 return assign_float(a);
338 #ifdef BOOST_HAS_FLOAT128
339 gmp_float_imp& operator= (float128_type a)
341 return assign_float(a);
344 gmp_float_imp& operator=(const char* s)
346 if (m_data[0]._mp_d == 0)
348 mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision()));
350 if (s && (*s == '+'))
351 ++s; // Leading "+" sign not supported by mpf_set_str:
352 if (0 != mpf_set_str(m_data, s, 10))
353 BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid floating point number.")));
356 void swap(gmp_float_imp& o) noexcept
358 mpf_swap(m_data, o.m_data);
360 std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
362 BOOST_MP_ASSERT(m_data[0]._mp_d);
364 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
365 bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
366 std::streamsize org_digits(digits);
368 if (scientific && digits)
373 void* (*alloc_func_ptr)(size_t);
374 void* (*realloc_func_ptr)(void*, size_t, size_t);
375 void (*free_func_ptr)(void*, size_t);
376 mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
378 if (mpf_sgn(m_data) == 0)
387 char* ps = mpf_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data);
388 --e; // To match with what our formatter expects.
391 // Oops we actually need a different number of digits to what we asked for:
392 (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
396 // We need to get *all* the digits and then possibly round up,
397 // we end up with either "0" or "1" as the result.
398 ps = mpf_get_str(0, &e, 10, 0, m_data);
400 unsigned offset = *ps == '-' ? 1 : 0;
401 if (ps[offset] > '5')
407 else if (ps[offset] == '5')
409 unsigned i = offset + 1;
410 bool round_up = false;
441 ps = mpf_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data);
442 --e; // To match with what our formatter expects.
445 // in some cases, when we ask for more digits of precision, it will
446 // change the number of digits to the left of the decimal, if that
447 // happens, account for it here.
448 // example: cout << fixed << setprecision(3) << mpf_float_50("99.9809")
450 (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
451 ps = mpf_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data);
452 --e; // To match with what our formatter expects.
457 ps = mpf_get_str(0, &e, 10, 1, m_data);
459 unsigned offset = *ps == '-' ? 1 : 0;
465 (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
467 boost::multiprecision::detail::format_float_string(result, e, org_digits, f, mpf_sgn(m_data) == 0);
470 ~gmp_float_imp() noexcept
477 void negate() noexcept
479 BOOST_MP_ASSERT(m_data[0]._mp_d);
480 mpf_neg(m_data, m_data);
482 int compare(const gmp_float<digits10>& o) const noexcept
484 BOOST_MP_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d);
485 return mpf_cmp(m_data, o.m_data);
487 int compare(long i) const noexcept
489 BOOST_MP_ASSERT(m_data[0]._mp_d);
490 return mpf_cmp_si(m_data, i);
492 int compare(unsigned long i) const noexcept
494 BOOST_MP_ASSERT(m_data[0]._mp_d);
495 return mpf_cmp_ui(m_data, i);
498 typename std::enable_if<boost::multiprecision::detail::is_arithmetic<V>::value, int>::type compare(V v) const
500 gmp_float<digits10> d;
504 mpf_t& data() noexcept
506 BOOST_MP_ASSERT(m_data[0]._mp_d);
509 const mpf_t& data() const noexcept
511 BOOST_MP_ASSERT(m_data[0]._mp_d);
517 static unsigned& get_default_precision() noexcept
519 static BOOST_MP_THREAD_LOCAL unsigned val(get_global_default_precision());
522 static boost::multiprecision::detail::precision_type& get_global_default_precision() noexcept
524 static boost::multiprecision::detail::precision_type val(50);
527 #ifndef BOOST_MT_NO_ATOMIC_INT
528 static std::atomic<variable_precision_options>& get_global_default_options() noexcept
530 static variable_precision_options& get_global_default_options() noexcept
533 #ifndef BOOST_MT_NO_ATOMIC_INT
534 static std::atomic<variable_precision_options> val{variable_precision_options::preserve_related_precision};
536 static variable_precision_options val{variable_precision_options::preserve_related_precision};
540 static variable_precision_options& get_default_options()noexcept
542 static BOOST_MP_THREAD_LOCAL variable_precision_options val(get_global_default_options());
545 static bool preserve_source_precision() noexcept
547 return get_default_options() >= variable_precision_options::preserve_source_precision;
555 void* (*alloc_func_ptr)(size_t);
556 void* (*realloc_func_ptr)(void*, size_t, size_t);
557 void (*free_func_ptr)(void*, size_t);
560 gmp_char_ptr() = delete;
561 explicit gmp_char_ptr(char* val_) : ptr_val {val_}
563 mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
565 ~gmp_char_ptr() noexcept
567 (*free_func_ptr)((void*)ptr_val, sizeof(*ptr_val));
570 inline char* get() noexcept { return ptr_val; }
573 } // namespace detail
578 template <unsigned digits10>
579 struct gmp_float : public detail::gmp_float_imp<digits10>
583 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
585 gmp_float(const gmp_float& o) : detail::gmp_float_imp<digits10>(o) {}
586 template <unsigned D>
587 gmp_float(const gmp_float<D>& o, typename std::enable_if<D <= digits10>::type* = 0);
588 template <unsigned D>
589 explicit gmp_float(const gmp_float<D>& o, typename std::enable_if<!(D <= digits10)>::type* = 0);
590 gmp_float(const gmp_int& o);
591 gmp_float(const gmp_rational& o);
592 gmp_float(const mpf_t val)
594 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
595 mpf_set(this->m_data, val);
597 gmp_float(const mpz_t val)
599 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
600 mpf_set_z(this->m_data, val);
602 gmp_float(const mpq_t val)
604 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
605 mpf_set_q(this->m_data, val);
608 gmp_float(gmp_float&& o) noexcept : detail::gmp_float_imp<digits10>(static_cast<detail::gmp_float_imp<digits10>&&>(o))
610 gmp_float& operator=(const gmp_float& o)
612 *static_cast<detail::gmp_float_imp<digits10>*>(this) = static_cast<detail::gmp_float_imp<digits10> const&>(o);
615 gmp_float& operator=(gmp_float&& o) noexcept
617 *static_cast<detail::gmp_float_imp<digits10>*>(this) = static_cast<detail::gmp_float_imp<digits10>&&>(o);
620 template <unsigned D>
621 gmp_float& operator=(const gmp_float<D>& o);
622 gmp_float& operator=(const gmp_int& o);
623 gmp_float& operator=(const gmp_rational& o);
624 gmp_float& operator=(const mpf_t val)
626 if (this->m_data[0]._mp_d == 0)
627 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
628 mpf_set(this->m_data, val);
631 gmp_float& operator=(const mpz_t val)
633 if (this->m_data[0]._mp_d == 0)
634 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
635 mpf_set_z(this->m_data, val);
638 gmp_float& operator=(const mpq_t val)
640 if (this->m_data[0]._mp_d == 0)
641 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
642 mpf_set_q(this->m_data, val);
646 typename std::enable_if<std::is_assignable<detail::gmp_float_imp<digits10>, V>::value, gmp_float&>::type operator=(const V& v)
648 *static_cast<detail::gmp_float_imp<digits10>*>(this) = v;
654 struct gmp_float<0> : public detail::gmp_float_imp<0>
657 // We have a problem with mpf_t in that the precision we request isn't what we get.
658 // As a result the front end can end up chasing it's tail trying to create a variable
659 // with the the correct precision to hold the result of an expression.
660 // See: https://github.com/boostorg/multiprecision/issues/164
661 // The problem is made worse by the fact that our conversions from base10 to 2 and
662 // vice-versa do not exactly round trip (and probably never will).
663 // The workaround is to keep track of the precision requested, and always return
664 // that as the current actual precision.
667 unsigned requested_precision;
670 gmp_float() : requested_precision(get_default_precision())
672 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
674 gmp_float(const mpf_t val) : requested_precision(get_default_precision())
676 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
677 mpf_set(this->m_data, val);
679 gmp_float(const mpz_t val) : requested_precision(get_default_precision())
681 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
682 mpf_set_z(this->m_data, val);
684 gmp_float(const mpq_t val) : requested_precision(get_default_precision())
686 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
687 mpf_set_q(this->m_data, val);
689 gmp_float(const gmp_float& o) : detail::gmp_float_imp<0>(o), requested_precision(preserve_source_precision() ? o.requested_precision : get_default_precision()) {}
690 template <unsigned D>
691 gmp_float(const gmp_float<D>& o)
693 mpf_init2(this->m_data, preserve_related_precision() ? mpf_get_prec(o.data()) : multiprecision::detail::digits10_2_2(get_default_precision()));
694 mpf_set(this->m_data, o.data());
695 requested_precision = preserve_related_precision() ? D : get_default_precision();
698 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())
700 gmp_float(const gmp_int& o);
701 gmp_float(const gmp_rational& o);
702 gmp_float(const gmp_float& o, unsigned digits10) : requested_precision(digits10)
704 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
705 mpf_set(this->m_data, o.data());
708 gmp_float(const V& o, unsigned digits10) : requested_precision(digits10)
710 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
714 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
716 // Support for new types in C++17
718 template <class Traits>
719 gmp_float(const std::basic_string_view<char, Traits>& o, unsigned digits10) : requested_precision(digits10)
721 using default_ops::assign_from_string_view;
722 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10));
723 assign_from_string_view(*this, o);
726 gmp_float& operator=(const gmp_float& o)
728 *static_cast<detail::gmp_float_imp<0>*>(this) = static_cast<detail::gmp_float_imp<0> const&>(o);
729 if(preserve_source_precision())
730 requested_precision = o.requested_precision;
734 gmp_float& operator=(gmp_float&& o) noexcept
736 *static_cast<detail::gmp_float_imp<0>*>(this) = static_cast<detail::gmp_float_imp<0>&&>(o);
737 if ((this->get_default_options() != variable_precision_options::preserve_target_precision))
738 requested_precision = o.requested_precision;
741 template <unsigned D>
742 gmp_float& operator=(const gmp_float<D>& o)
744 if (this->m_data[0]._mp_d == 0)
746 mpf_init2(this->m_data, preserve_related_precision() ? mpf_get_prec(o.data()) : multiprecision::detail::digits10_2_2(get_default_precision()));
748 else if(preserve_related_precision())
750 mpf_set_prec(this->m_data, mpf_get_prec(o.data()));
752 mpf_set(this->m_data, o.data());
753 if (preserve_related_precision())
754 requested_precision = D;
757 gmp_float& operator=(const gmp_int& o);
758 gmp_float& operator=(const gmp_rational& o);
759 gmp_float& operator=(const mpf_t val)
761 if (this->m_data[0]._mp_d == 0)
763 requested_precision = get_default_precision();
764 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
766 mpf_set(this->m_data, val);
769 gmp_float& operator=(const mpz_t val)
771 if (this->m_data[0]._mp_d == 0)
773 requested_precision = get_default_precision();
774 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
776 mpf_set_z(this->m_data, val);
779 gmp_float& operator=(const mpq_t val)
781 if (this->m_data[0]._mp_d == 0)
783 requested_precision = get_default_precision();
784 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
786 mpf_set_q(this->m_data, val);
790 typename std::enable_if<std::is_assignable<detail::gmp_float_imp<0>, V>::value, gmp_float&>::type operator=(const V& v)
792 constexpr unsigned d10 = std::is_floating_point<V>::value ?
793 std::numeric_limits<V>::digits10 :
794 std::numeric_limits<V>::digits10 ? 1 + std::numeric_limits<V>::digits10 :
795 1 + boost::multiprecision::detail::digits2_2_10(std::numeric_limits<V>::digits);
796 if((thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision) && (precision() < d10))
797 this->precision(d10);
798 *static_cast<detail::gmp_float_imp<0>*>(this) = v;
801 static unsigned default_precision() noexcept
803 return get_global_default_precision();
805 static void default_precision(unsigned v) noexcept
807 get_global_default_precision() = v;
809 static unsigned thread_default_precision() noexcept
811 return get_default_precision();
813 static void thread_default_precision(unsigned v) noexcept
815 get_default_precision() = v;
817 unsigned precision() const noexcept
819 return requested_precision;
821 void precision(unsigned digits10) noexcept
823 requested_precision = digits10;
824 mpf_set_prec(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
827 // Variable precision options:
829 static variable_precision_options default_variable_precision_options()noexcept
831 return get_global_default_options();
833 static variable_precision_options thread_default_variable_precision_options()noexcept
835 return get_default_options();
837 static void default_variable_precision_options(variable_precision_options opts)
839 get_global_default_options() = opts;
841 static void thread_default_variable_precision_options(variable_precision_options opts)
843 get_default_options() = opts;
845 static bool preserve_source_precision()
847 return get_default_options() >= variable_precision_options::preserve_source_precision;
849 static bool preserve_related_precision()
851 return get_default_options() >= variable_precision_options::preserve_related_precision;
853 static bool preserve_all_precision()
855 return get_default_options() >= variable_precision_options::preserve_all_precision;
860 void swap(gmp_float& o)
862 std::swap(requested_precision, o.requested_precision);
863 gmp_float_imp<0>::swap(o);
867 template <unsigned digits10, class T>
868 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
870 return a.compare(b) == 0;
872 template <unsigned digits10, class T>
873 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
875 return a.compare(b) < 0;
877 template <unsigned digits10, class T>
878 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
880 return a.compare(b) > 0;
883 template <unsigned D1, unsigned D2>
884 inline void eval_add(gmp_float<D1>& result, const gmp_float<D2>& o)
886 mpf_add(result.data(), result.data(), o.data());
888 template <unsigned D1, unsigned D2>
889 inline void eval_subtract(gmp_float<D1>& result, const gmp_float<D2>& o)
891 mpf_sub(result.data(), result.data(), o.data());
893 template <unsigned D1, unsigned D2>
894 inline void eval_multiply(gmp_float<D1>& result, const gmp_float<D2>& o)
896 mpf_mul(result.data(), result.data(), o.data());
898 template <unsigned digits10>
899 inline bool eval_is_zero(const gmp_float<digits10>& val) noexcept
901 return mpf_sgn(val.data()) == 0;
903 template <unsigned D1, unsigned D2>
904 inline void eval_divide(gmp_float<D1>& result, const gmp_float<D2>& o)
907 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
908 mpf_div(result.data(), result.data(), o.data());
910 template <unsigned digits10>
911 inline void eval_add(gmp_float<digits10>& result, unsigned long i)
913 mpf_add_ui(result.data(), result.data(), i);
915 template <unsigned digits10>
916 inline void eval_subtract(gmp_float<digits10>& result, unsigned long i)
918 mpf_sub_ui(result.data(), result.data(), i);
920 template <unsigned digits10>
921 inline void eval_multiply(gmp_float<digits10>& result, unsigned long i)
923 mpf_mul_ui(result.data(), result.data(), i);
925 template <unsigned digits10>
926 inline void eval_divide(gmp_float<digits10>& result, unsigned long i)
929 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
930 mpf_div_ui(result.data(), result.data(), i);
932 template <unsigned digits10>
933 inline void eval_add(gmp_float<digits10>& result, long i)
936 mpf_add_ui(result.data(), result.data(), i);
938 mpf_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
940 template <unsigned digits10>
941 inline void eval_subtract(gmp_float<digits10>& result, long i)
944 mpf_sub_ui(result.data(), result.data(), i);
946 mpf_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
948 template <unsigned digits10>
949 inline void eval_multiply(gmp_float<digits10>& result, long i)
951 mpf_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
953 mpf_neg(result.data(), result.data());
955 template <unsigned digits10>
956 inline void eval_divide(gmp_float<digits10>& result, long i)
959 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
960 mpf_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i));
962 mpf_neg(result.data(), result.data());
965 // Specialised 3 arg versions of the basic operators:
967 template <unsigned D1, unsigned D2, unsigned D3>
968 inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
970 mpf_add(a.data(), x.data(), y.data());
972 template <unsigned D1, unsigned D2>
973 inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
975 mpf_add_ui(a.data(), x.data(), y);
977 template <unsigned D1, unsigned D2>
978 inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
981 mpf_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
983 mpf_add_ui(a.data(), x.data(), y);
985 template <unsigned D1, unsigned D2>
986 inline void eval_add(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
988 mpf_add_ui(a.data(), y.data(), x);
990 template <unsigned D1, unsigned D2>
991 inline void eval_add(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
995 mpf_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data());
996 mpf_neg(a.data(), a.data());
999 mpf_add_ui(a.data(), y.data(), x);
1001 template <unsigned D1, unsigned D2, unsigned D3>
1002 inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
1004 mpf_sub(a.data(), x.data(), y.data());
1006 template <unsigned D1, unsigned D2>
1007 inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
1009 mpf_sub_ui(a.data(), x.data(), y);
1011 template <unsigned D1, unsigned D2>
1012 inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
1015 mpf_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
1017 mpf_sub_ui(a.data(), x.data(), y);
1019 template <unsigned D1, unsigned D2>
1020 inline void eval_subtract(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
1022 mpf_ui_sub(a.data(), x, y.data());
1024 template <unsigned D1, unsigned D2>
1025 inline void eval_subtract(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
1029 mpf_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x));
1030 mpf_neg(a.data(), a.data());
1033 mpf_ui_sub(a.data(), x, y.data());
1036 template <unsigned D1, unsigned D2, unsigned D3>
1037 inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
1039 mpf_mul(a.data(), x.data(), y.data());
1041 template <unsigned D1, unsigned D2>
1042 inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
1044 mpf_mul_ui(a.data(), x.data(), y);
1046 template <unsigned D1, unsigned D2>
1047 inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
1051 mpf_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
1055 mpf_mul_ui(a.data(), x.data(), y);
1057 template <unsigned D1, unsigned D2>
1058 inline void eval_multiply(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
1060 mpf_mul_ui(a.data(), y.data(), x);
1062 template <unsigned D1, unsigned D2>
1063 inline void eval_multiply(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
1067 mpf_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x));
1068 mpf_neg(a.data(), a.data());
1071 mpf_mul_ui(a.data(), y.data(), x);
1074 template <unsigned D1, unsigned D2, unsigned D3>
1075 inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y)
1077 if (eval_is_zero(y))
1078 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1079 mpf_div(a.data(), x.data(), y.data());
1081 template <unsigned D1, unsigned D2>
1082 inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y)
1085 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1086 mpf_div_ui(a.data(), x.data(), y);
1088 template <unsigned D1, unsigned D2>
1089 inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, long y)
1092 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1095 mpf_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y));
1099 mpf_div_ui(a.data(), x.data(), y);
1101 template <unsigned D1, unsigned D2>
1102 inline void eval_divide(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y)
1104 if (eval_is_zero(y))
1105 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1106 mpf_ui_div(a.data(), x, y.data());
1108 template <unsigned D1, unsigned D2>
1109 inline void eval_divide(gmp_float<D1>& a, long x, const gmp_float<D2>& y)
1111 if (eval_is_zero(y))
1112 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1115 mpf_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data());
1116 mpf_neg(a.data(), a.data());
1119 mpf_ui_div(a.data(), x, y.data());
1122 template <unsigned digits10>
1123 inline int eval_get_sign(const gmp_float<digits10>& val) noexcept
1125 return mpf_sgn(val.data());
1128 template <unsigned digits10>
1129 inline void eval_convert_to(unsigned long* result, const gmp_float<digits10>& val) noexcept
1131 if (0 == mpf_fits_ulong_p(val.data()))
1132 *result = (std::numeric_limits<unsigned long>::max)();
1134 *result = static_cast<unsigned long>(mpf_get_ui(val.data()));
1136 template <unsigned digits10>
1137 inline void eval_convert_to(long* result, const gmp_float<digits10>& val) noexcept
1139 if (0 == mpf_fits_slong_p(val.data()))
1141 *result = (std::numeric_limits<long>::max)();
1142 *result *= mpf_sgn(val.data());
1145 *result = static_cast<long>(mpf_get_si(val.data()));
1147 #ifdef BOOST_MP_STANDALONE
1148 template <unsigned digits10>
1149 inline void eval_convert_to(long double* result, const gmp_float<digits10>& val) noexcept
1153 detail::gmp_char_ptr val_char_ptr {mpf_get_str(nullptr, &exp, 10, LDBL_DIG, val.data())};
1155 auto temp_string = std::string(val_char_ptr.get());
1156 if(exp > 0 && static_cast<std::size_t>(exp) < temp_string.size())
1158 if(temp_string.front() == '-')
1163 temp_string.insert(exp, 1, '.');
1166 *result = std::strtold(temp_string.c_str(), nullptr);
1168 if((temp_string.size() == 2ul && *result < 0.0l) ||
1169 (static_cast<std::size_t>(exp) > temp_string.size()))
1171 *result *= std::pow(10l, exp-1);
1174 #endif // BOOST_MP_STANDALONE
1175 template <unsigned digits10>
1176 inline void eval_convert_to(double* result, const gmp_float<digits10>& val) noexcept
1178 *result = mpf_get_d(val.data());
1180 #ifdef BOOST_HAS_LONG_LONG
1181 template <unsigned digits10>
1182 inline void eval_convert_to(long long* result, const gmp_float<digits10>& val)
1184 gmp_float<digits10> t(val);
1185 if (eval_get_sign(t) < 0)
1188 long digits = std::numeric_limits<long long>::digits - std::numeric_limits<long>::digits;
1191 mpf_div_2exp(t.data(), t.data(), digits);
1193 if (!mpf_fits_slong_p(t.data()))
1195 if (eval_get_sign(val) < 0)
1196 *result = (std::numeric_limits<long long>::min)();
1198 *result = (std::numeric_limits<long long>::max)();
1202 *result = mpf_get_si(t.data());
1206 digits -= std::numeric_limits<unsigned long>::digits;
1207 mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits<unsigned long>::digits : std::numeric_limits<unsigned long>::digits + digits);
1208 unsigned long l = static_cast<unsigned long>(mpf_get_ui(t.data()));
1213 if (eval_get_sign(val) < 0)
1216 template <unsigned digits10>
1217 inline void eval_convert_to(unsigned long long* result, const gmp_float<digits10>& val)
1219 gmp_float<digits10> t(val);
1221 long digits = std::numeric_limits<long long>::digits - std::numeric_limits<long>::digits;
1224 mpf_div_2exp(t.data(), t.data(), digits);
1226 if (!mpf_fits_ulong_p(t.data()))
1228 *result = (std::numeric_limits<long long>::max)();
1232 *result = mpf_get_ui(t.data());
1236 digits -= std::numeric_limits<unsigned long>::digits;
1237 mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits<unsigned long>::digits : std::numeric_limits<unsigned long>::digits + digits);
1238 unsigned long l = static_cast<unsigned long>(mpf_get_ui(t.data()));
1247 #ifdef BOOST_HAS_FLOAT128
1248 template <unsigned digits10>
1249 inline void eval_convert_to(float128_type* result, const gmp_float<digits10>& val)
1251 *result = float128_procs::strtoflt128(val.str(0, std::ios_base::scientific).c_str(), nullptr);
1257 // Native non-member operations:
1259 template <unsigned Digits10>
1260 inline void eval_sqrt(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1262 mpf_sqrt(result.data(), val.data());
1265 template <unsigned Digits10>
1266 inline void eval_abs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1268 mpf_abs(result.data(), val.data());
1271 template <unsigned Digits10>
1272 inline void eval_fabs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1274 mpf_abs(result.data(), val.data());
1276 template <unsigned Digits10>
1277 inline void eval_ceil(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1279 mpf_ceil(result.data(), val.data());
1281 template <unsigned Digits10>
1282 inline void eval_floor(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1284 mpf_floor(result.data(), val.data());
1286 template <unsigned Digits10>
1287 inline void eval_trunc(gmp_float<Digits10>& result, const gmp_float<Digits10>& val)
1289 mpf_trunc(result.data(), val.data());
1291 template <unsigned Digits10>
1292 inline void eval_ldexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long e)
1295 mpf_mul_2exp(result.data(), val.data(), e);
1297 mpf_div_2exp(result.data(), val.data(), -e);
1301 template <unsigned Digits10>
1302 inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, int* e)
1304 #if (BOOST_MP_MPIR_VERSION >= 20600) && (BOOST_MP_MPIR_VERSION < 30000)
1306 mpf_get_d_2exp(&v, val.data());
1309 mpf_get_d_2exp(&v, val.data());
1312 eval_ldexp(result, val, -v);
1314 template <unsigned Digits10>
1315 inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long* e)
1317 #if (BOOST_MP_MPIR_VERSION >= 20600) && (BOOST_MP_MPIR_VERSION < 30000)
1319 mpf_get_d_2exp(&v, val.data());
1321 eval_ldexp(result, val, -v);
1323 mpf_get_d_2exp(e, val.data());
1324 eval_ldexp(result, val, -*e);
1328 template <unsigned Digits10>
1329 inline std::size_t hash_value(const gmp_float<Digits10>& val)
1331 std::size_t result = 0;
1332 for (int i = 0; i < std::abs(val.data()[0]._mp_size); ++i)
1333 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_d[i]);
1334 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_exp, val.data()[0]._mp_size);
1340 #ifdef BOOST_HAS_LONG_LONG
1341 using signed_types = std::tuple<long, long long> ;
1342 using unsigned_types = std::tuple<unsigned long, unsigned long long>;
1344 using signed_types = std::tuple<long> ;
1345 using unsigned_types = std::tuple<unsigned long>;
1347 using float_types = std::tuple<double, long double>;
1351 mpz_init(this->m_data);
1353 gmp_int(const gmp_int& o)
1355 if (o.m_data[0]._mp_d)
1356 mpz_init_set(m_data, o.m_data);
1358 mpz_init(this->m_data);
1361 gmp_int(gmp_int&& o) noexcept
1363 m_data[0] = o.m_data[0];
1364 o.m_data[0]._mp_d = 0;
1366 explicit gmp_int(const mpf_t val)
1368 mpz_init(this->m_data);
1369 mpz_set_f(this->m_data, val);
1371 gmp_int(const mpz_t val)
1373 mpz_init_set(this->m_data, val);
1377 mpz_init_set_si(this->m_data, i);
1379 gmp_int(unsigned long i)
1381 mpz_init_set_ui(this->m_data, i);
1383 explicit gmp_int(const mpq_t val)
1385 mpz_init(this->m_data);
1386 mpz_set_q(this->m_data, val);
1388 template <unsigned Digits10>
1389 explicit gmp_int(const gmp_float<Digits10>& o)
1391 mpz_init(this->m_data);
1392 mpz_set_f(this->m_data, o.data());
1394 explicit gmp_int(const gmp_rational& o);
1395 gmp_int& operator=(const gmp_int& o)
1397 if (m_data[0]._mp_d == 0)
1398 mpz_init(this->m_data);
1399 mpz_set(m_data, o.m_data);
1403 gmp_int& operator=(gmp_int&& o) noexcept
1405 mpz_swap(m_data, o.m_data);
1408 #ifdef BOOST_HAS_LONG_LONG
1409 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
1410 gmp_int& operator=(unsigned long long i)
1412 *this = static_cast<unsigned long>(i);
1416 gmp_int& operator=(unsigned long long i)
1418 if (m_data[0]._mp_d == 0)
1419 mpz_init(this->m_data);
1420 unsigned long long mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
1423 mpz_set_ui(m_data, 0);
1424 mpz_init_set_ui(t, 0);
1427 mpz_set_ui(t, static_cast<unsigned long>(i & mask));
1429 mpz_mul_2exp(t, t, shift);
1430 mpz_add(m_data, m_data, t);
1431 shift += std::numeric_limits<unsigned long>::digits;
1432 i >>= std::numeric_limits<unsigned long>::digits;
1438 gmp_int& operator=(long long i)
1440 if (m_data[0]._mp_d == 0)
1441 mpz_init(this->m_data);
1443 *this = boost::multiprecision::detail::unsigned_abs(i);
1445 mpz_neg(m_data, m_data);
1449 #ifdef BOOST_HAS_INT128
1450 gmp_int& operator=(uint128_type i)
1452 if (m_data[0]._mp_d == 0)
1453 mpz_init(this->m_data);
1454 uint128_type mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL);
1457 mpz_set_ui(m_data, 0);
1458 mpz_init_set_ui(t, 0);
1461 mpz_set_ui(t, static_cast<unsigned long>(i & mask));
1463 mpz_mul_2exp(t, t, shift);
1464 mpz_add(m_data, m_data, t);
1465 shift += std::numeric_limits<unsigned long>::digits;
1466 i >>= std::numeric_limits<unsigned long>::digits;
1471 gmp_int& operator=(int128_type i)
1473 if (m_data[0]._mp_d == 0)
1474 mpz_init(this->m_data);
1476 *this = boost::multiprecision::detail::unsigned_abs(i);
1478 mpz_neg(m_data, m_data);
1482 gmp_int& operator=(unsigned long i)
1484 if (m_data[0]._mp_d == 0)
1485 mpz_init(this->m_data);
1486 mpz_set_ui(m_data, i);
1489 gmp_int& operator=(long i)
1491 if (m_data[0]._mp_d == 0)
1492 mpz_init(this->m_data);
1493 mpz_set_si(m_data, i);
1496 gmp_int& operator=(double d)
1498 if (m_data[0]._mp_d == 0)
1499 mpz_init(this->m_data);
1500 mpz_set_d(m_data, d);
1504 gmp_int& assign_float(F a)
1506 BOOST_MP_FLOAT128_USING using std::floor; using std::frexp; using std::ldexp;
1508 if (m_data[0]._mp_d == 0)
1509 mpz_init(this->m_data);
1513 mpz_set_si(m_data, 0);
1519 mpz_set_si(m_data, 1);
1523 BOOST_MP_ASSERT(!BOOST_MP_ISINF(a));
1524 BOOST_MP_ASSERT(!BOOST_MP_ISNAN(a));
1528 mpz_set_ui(m_data, 0u);
1532 constexpr const int shift = std::numeric_limits<int>::digits - 1;
1536 // extract int sized bits from f:
1537 f = ldexp(f, shift);
1540 mpz_mul_2exp(m_data, m_data, shift);
1542 mpz_add_ui(m_data, m_data, static_cast<unsigned>(term));
1544 mpz_sub_ui(m_data, m_data, static_cast<unsigned>(-term));
1548 mpz_mul_2exp(m_data, m_data, e);
1550 mpz_div_2exp(m_data, m_data, -e);
1553 gmp_int& operator=(long double a)
1555 return assign_float(a);
1557 gmp_int& operator=(const char* s)
1559 if (m_data[0]._mp_d == 0)
1560 mpz_init(this->m_data);
1561 std::size_t n = s ? std::strlen(s) : 0;
1563 if (n && (*s == '0'))
1565 if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X')))
1579 if (0 != mpz_set_str(m_data, s, radix))
1580 BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid integer.")));
1583 mpz_set_ui(m_data, 0);
1586 #ifdef BOOST_HAS_FLOAT128
1587 gmp_int& operator=(float128_type a)
1589 return assign_float(a);
1592 gmp_int& operator=(const mpf_t val)
1594 if (m_data[0]._mp_d == 0)
1595 mpz_init(this->m_data);
1596 mpz_set_f(this->m_data, val);
1599 gmp_int& operator=(const mpz_t val)
1601 if (m_data[0]._mp_d == 0)
1602 mpz_init(this->m_data);
1603 mpz_set(this->m_data, val);
1606 gmp_int& operator=(const mpq_t val)
1608 if (m_data[0]._mp_d == 0)
1609 mpz_init(this->m_data);
1610 mpz_set_q(this->m_data, val);
1613 template <unsigned Digits10>
1614 gmp_int& operator=(const gmp_float<Digits10>& o)
1616 if (m_data[0]._mp_d == 0)
1617 mpz_init(this->m_data);
1618 mpz_set_f(this->m_data, o.data());
1621 gmp_int& operator=(const gmp_rational& o);
1622 void swap(gmp_int& o)
1624 mpz_swap(m_data, o.m_data);
1626 std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f) const
1628 BOOST_MP_ASSERT(m_data[0]._mp_d);
1631 if ((f & std::ios_base::oct) == std::ios_base::oct)
1633 else if ((f & std::ios_base::hex) == std::ios_base::hex)
1636 // sanity check, bases 8 and 16 are only available for positive numbers:
1638 if ((base != 10) && (mpz_sgn(m_data) < 0))
1639 BOOST_MP_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers"));
1640 void* (*alloc_func_ptr)(size_t);
1641 void* (*realloc_func_ptr)(void*, size_t, size_t);
1642 void (*free_func_ptr)(void*, size_t);
1643 const char* ps = mpz_get_str(0, base, m_data);
1645 mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
1646 (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
1647 if (f & std::ios_base::uppercase)
1648 for (size_t i = 0; i < s.length(); ++i)
1649 s[i] = static_cast<char>(std::toupper(s[i]));
1650 if ((base != 10) && (f & std::ios_base::showbase))
1652 int pos = s[0] == '-' ? 1 : 0;
1653 const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x";
1654 s.insert(static_cast<std::string::size_type>(pos), pp);
1656 if ((f & std::ios_base::showpos) && (s[0] != '-'))
1657 s.insert(static_cast<std::string::size_type>(0), 1, '+');
1663 if (m_data[0]._mp_d)
1666 void negate() noexcept
1668 BOOST_MP_ASSERT(m_data[0]._mp_d);
1669 mpz_neg(m_data, m_data);
1671 int compare(const gmp_int& o) const noexcept
1673 BOOST_MP_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d);
1674 return mpz_cmp(m_data, o.m_data);
1676 int compare(long i) const noexcept
1678 BOOST_MP_ASSERT(m_data[0]._mp_d);
1679 return mpz_cmp_si(m_data, i);
1681 int compare(unsigned long i) const noexcept
1683 BOOST_MP_ASSERT(m_data[0]._mp_d);
1684 return mpz_cmp_ui(m_data, i);
1687 int compare(V v) const
1693 mpz_t& data() noexcept
1695 BOOST_MP_ASSERT(m_data[0]._mp_d);
1698 const mpz_t& data() const noexcept
1700 BOOST_MP_ASSERT(m_data[0]._mp_d);
1709 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_eq(const gmp_int& a, const T& b)
1711 return a.compare(b) == 0;
1714 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_lt(const gmp_int& a, const T& b)
1716 return a.compare(b) < 0;
1719 inline typename std::enable_if<boost::multiprecision::detail::is_arithmetic<T>::value, bool>::type eval_gt(const gmp_int& a, const T& b)
1721 return a.compare(b) > 0;
1724 inline bool eval_is_zero(const gmp_int& val)
1726 return mpz_sgn(val.data()) == 0;
1728 inline void eval_add(gmp_int& t, const gmp_int& o)
1730 mpz_add(t.data(), t.data(), o.data());
1732 inline void eval_multiply_add(gmp_int& t, const gmp_int& a, const gmp_int& b)
1734 mpz_addmul(t.data(), a.data(), b.data());
1736 inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, const gmp_int& b)
1738 mpz_submul(t.data(), a.data(), b.data());
1740 inline void eval_subtract(gmp_int& t, const gmp_int& o)
1742 mpz_sub(t.data(), t.data(), o.data());
1744 inline void eval_multiply(gmp_int& t, const gmp_int& o)
1746 mpz_mul(t.data(), t.data(), o.data());
1748 inline void eval_divide(gmp_int& t, const gmp_int& o)
1750 if (eval_is_zero(o))
1751 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1752 mpz_tdiv_q(t.data(), t.data(), o.data());
1754 inline void eval_modulus(gmp_int& t, const gmp_int& o)
1756 mpz_tdiv_r(t.data(), t.data(), o.data());
1758 inline void eval_add(gmp_int& t, unsigned long i)
1760 mpz_add_ui(t.data(), t.data(), i);
1762 inline void eval_multiply_add(gmp_int& t, const gmp_int& a, unsigned long i)
1764 mpz_addmul_ui(t.data(), a.data(), i);
1766 inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, unsigned long i)
1768 mpz_submul_ui(t.data(), a.data(), i);
1770 inline void eval_subtract(gmp_int& t, unsigned long i)
1772 mpz_sub_ui(t.data(), t.data(), i);
1774 inline void eval_multiply(gmp_int& t, unsigned long i)
1776 mpz_mul_ui(t.data(), t.data(), i);
1778 inline void eval_modulus(gmp_int& t, unsigned long i)
1780 mpz_tdiv_r_ui(t.data(), t.data(), i);
1782 inline void eval_divide(gmp_int& t, unsigned long i)
1785 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1786 mpz_tdiv_q_ui(t.data(), t.data(), i);
1788 inline void eval_add(gmp_int& t, long i)
1791 mpz_add_ui(t.data(), t.data(), i);
1793 mpz_sub_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i));
1795 inline void eval_multiply_add(gmp_int& t, const gmp_int& a, long i)
1798 mpz_addmul_ui(t.data(), a.data(), i);
1800 mpz_submul_ui(t.data(), a.data(), boost::multiprecision::detail::unsigned_abs(i));
1802 inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, long i)
1805 mpz_submul_ui(t.data(), a.data(), i);
1807 mpz_addmul_ui(t.data(), a.data(), boost::multiprecision::detail::unsigned_abs(i));
1809 inline void eval_subtract(gmp_int& t, long i)
1812 mpz_sub_ui(t.data(), t.data(), i);
1814 mpz_add_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i));
1816 inline void eval_multiply(gmp_int& t, long i)
1818 mpz_mul_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i));
1820 mpz_neg(t.data(), t.data());
1822 inline void eval_modulus(gmp_int& t, long i)
1824 mpz_tdiv_r_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i));
1826 inline void eval_divide(gmp_int& t, long i)
1829 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1830 mpz_tdiv_q_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i));
1832 mpz_neg(t.data(), t.data());
1835 inline void eval_left_shift(gmp_int& t, UI i)
1837 mpz_mul_2exp(t.data(), t.data(), static_cast<unsigned long>(i));
1840 inline void eval_right_shift(gmp_int& t, UI i)
1842 mpz_fdiv_q_2exp(t.data(), t.data(), static_cast<unsigned long>(i));
1845 inline void eval_left_shift(gmp_int& t, const gmp_int& v, UI i)
1847 mpz_mul_2exp(t.data(), v.data(), static_cast<unsigned long>(i));
1850 inline void eval_right_shift(gmp_int& t, const gmp_int& v, UI i)
1852 mpz_fdiv_q_2exp(t.data(), v.data(), static_cast<unsigned long>(i));
1855 inline void eval_bitwise_and(gmp_int& result, const gmp_int& v)
1857 mpz_and(result.data(), result.data(), v.data());
1860 inline void eval_bitwise_or(gmp_int& result, const gmp_int& v)
1862 mpz_ior(result.data(), result.data(), v.data());
1865 inline void eval_bitwise_xor(gmp_int& result, const gmp_int& v)
1867 mpz_xor(result.data(), result.data(), v.data());
1870 inline void eval_add(gmp_int& t, const gmp_int& p, const gmp_int& o)
1872 mpz_add(t.data(), p.data(), o.data());
1874 inline void eval_subtract(gmp_int& t, const gmp_int& p, const gmp_int& o)
1876 mpz_sub(t.data(), p.data(), o.data());
1878 inline void eval_multiply(gmp_int& t, const gmp_int& p, const gmp_int& o)
1880 mpz_mul(t.data(), p.data(), o.data());
1882 inline void eval_divide(gmp_int& t, const gmp_int& p, const gmp_int& o)
1884 if (eval_is_zero(o))
1885 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1886 mpz_tdiv_q(t.data(), p.data(), o.data());
1888 inline void eval_modulus(gmp_int& t, const gmp_int& p, const gmp_int& o)
1890 mpz_tdiv_r(t.data(), p.data(), o.data());
1892 inline void eval_add(gmp_int& t, const gmp_int& p, unsigned long i)
1894 mpz_add_ui(t.data(), p.data(), i);
1896 inline void eval_subtract(gmp_int& t, const gmp_int& p, unsigned long i)
1898 mpz_sub_ui(t.data(), p.data(), i);
1900 inline void eval_multiply(gmp_int& t, const gmp_int& p, unsigned long i)
1902 mpz_mul_ui(t.data(), p.data(), i);
1904 inline void eval_modulus(gmp_int& t, const gmp_int& p, unsigned long i)
1906 mpz_tdiv_r_ui(t.data(), p.data(), i);
1908 inline void eval_divide(gmp_int& t, const gmp_int& p, unsigned long i)
1911 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1912 mpz_tdiv_q_ui(t.data(), p.data(), i);
1914 inline void eval_add(gmp_int& t, const gmp_int& p, long i)
1917 mpz_add_ui(t.data(), p.data(), i);
1919 mpz_sub_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
1921 inline void eval_subtract(gmp_int& t, const gmp_int& p, long i)
1924 mpz_sub_ui(t.data(), p.data(), i);
1926 mpz_add_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
1928 inline void eval_multiply(gmp_int& t, const gmp_int& p, long i)
1930 mpz_mul_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
1932 mpz_neg(t.data(), t.data());
1934 inline void eval_modulus(gmp_int& t, const gmp_int& p, long i)
1936 mpz_tdiv_r_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
1938 inline void eval_divide(gmp_int& t, const gmp_int& p, long i)
1941 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
1942 mpz_tdiv_q_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i));
1944 mpz_neg(t.data(), t.data());
1947 inline void eval_bitwise_and(gmp_int& result, const gmp_int& u, const gmp_int& v)
1949 mpz_and(result.data(), u.data(), v.data());
1952 inline void eval_bitwise_or(gmp_int& result, const gmp_int& u, const gmp_int& v)
1954 mpz_ior(result.data(), u.data(), v.data());
1957 inline void eval_bitwise_xor(gmp_int& result, const gmp_int& u, const gmp_int& v)
1959 mpz_xor(result.data(), u.data(), v.data());
1962 inline void eval_complement(gmp_int& result, const gmp_int& u)
1964 mpz_com(result.data(), u.data());
1967 inline int eval_get_sign(const gmp_int& val)
1969 return mpz_sgn(val.data());
1971 inline void eval_convert_to(unsigned long* result, const gmp_int& val)
1973 if (mpz_sgn(val.data()) < 0)
1975 BOOST_MP_THROW_EXCEPTION(std::range_error("Conversion from negative integer to an unsigned type results in undefined behaviour"));
1978 *result = static_cast<unsigned long>(mpz_get_ui(val.data()));
1980 inline void eval_convert_to(long* result, const gmp_int& val)
1982 if (0 == mpz_fits_slong_p(val.data()))
1984 *result = mpz_sgn(val.data()) < 0 ? (std::numeric_limits<long>::min)() : (std::numeric_limits<long>::max)();
1987 *result = static_cast<long>(mpz_get_si(val.data()));
1989 inline void eval_convert_to(long double* result, const gmp_int& val)
1991 detail::gmp_char_ptr val_char_ptr {mpz_get_str(nullptr, 10, val.data())};
1992 *result = std::strtold(val_char_ptr.get(), nullptr);
1994 inline void eval_convert_to(double* result, const gmp_int& val)
1996 *result = mpz_get_d(val.data());
1998 #ifdef BOOST_HAS_LONG_LONG
1999 inline void eval_convert_to(unsigned long long* result, const gmp_int& val)
2001 if (mpz_sgn(val.data()) < 0)
2003 BOOST_MP_THROW_EXCEPTION(std::range_error("Conversion from negative integer to an unsigned type results in undefined behaviour"));
2007 unsigned parts = sizeof(unsigned long long) / sizeof(unsigned long);
2009 for (unsigned i = 0; i < parts; ++i)
2011 unsigned long long part = mpz_get_ui(t.data());
2013 *result |= part << (i * sizeof(unsigned long) * CHAR_BIT);
2016 mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT);
2019 inline void eval_convert_to(long long* result, const gmp_int& val)
2021 int s = mpz_sgn(val.data());
2024 unsigned parts = sizeof(unsigned long long) / sizeof(unsigned long);
2025 unsigned long long unsigned_result = 0;
2027 for (unsigned i = 0; i < parts; ++i)
2029 unsigned long long part = mpz_get_ui(t.data());
2031 unsigned_result |= part << (i * sizeof(unsigned long) * CHAR_BIT);
2033 unsigned_result = part;
2034 mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT);
2039 bool overflow = false;
2040 if (mpz_sgn(t.data()))
2044 if ((s > 0) && (unsigned_result > static_cast<unsigned long long>((std::numeric_limits<long long>::max)())))
2046 if((s < 0) && (unsigned_result > 1u - static_cast<unsigned long long>((std::numeric_limits<long long>::min)() + 1)))
2049 *result = s < 0 ? (std::numeric_limits<long long>::min)() : (std::numeric_limits<long long>::max)();
2051 *result = s < 0 ? -static_cast<long long>(unsigned_result - 1) - 1 : unsigned_result;
2054 #ifdef BOOST_HAS_INT128
2055 inline void eval_convert_to(uint128_type* result, const gmp_int& val)
2057 if (mpz_sgn(val.data()) < 0)
2059 BOOST_MP_THROW_EXCEPTION(std::range_error("Conversion from negative integer to an unsigned type results in undefined behaviour"));
2063 unsigned parts = sizeof(uint128_type) / sizeof(unsigned long);
2065 for (unsigned i = 0; i < parts; ++i)
2067 uint128_type part = mpz_get_ui(t.data());
2069 *result |= part << (i * sizeof(unsigned long) * CHAR_BIT);
2072 mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT);
2075 inline void eval_convert_to(int128_type* result, const gmp_int& val)
2077 int s = mpz_sgn(val.data());
2080 unsigned parts = sizeof(uint128_type) / sizeof(unsigned long);
2081 uint128_type unsigned_result = 0;
2083 for (unsigned i = 0; i < parts; ++i)
2085 uint128_type part = mpz_get_ui(t.data());
2087 unsigned_result |= part << (i * sizeof(unsigned long) * CHAR_BIT);
2089 unsigned_result = part;
2090 mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT);
2095 constexpr const int128_type int128_max = static_cast<int128_type>((static_cast<uint128_type>(1u) << 127) - 1);
2096 constexpr const int128_type int128_min = (static_cast<uint128_type>(1u) << 127);
2097 bool overflow = false;
2098 if (mpz_sgn(t.data()))
2102 if ((s > 0) && (unsigned_result > static_cast<uint128_type>(int128_max)))
2104 if ((s < 0) && (unsigned_result > 1u - static_cast<uint128_type>(int128_min + 1)))
2107 *result = s < 0 ? int128_min : int128_max;
2109 *result = s < 0 ? -int128_type(unsigned_result - 1) - 1 : unsigned_result;
2112 template <unsigned digits10>
2113 inline void eval_convert_to(int128_type* result, const gmp_float<digits10>& val)
2116 mpz_set_f(i.data(), val.data());
2117 eval_convert_to(result, i);
2119 template <unsigned digits10>
2120 inline void eval_convert_to(uint128_type* result, const gmp_float<digits10>& val)
2123 mpz_set_f(i.data(), val.data());
2124 eval_convert_to(result, i);
2129 #ifdef BOOST_HAS_FLOAT128
2130 inline void eval_convert_to(float128_type* result, const gmp_int& val)
2132 *result = float128_procs::strtoflt128(val.str(0, std::ios_base::fixed).c_str(), nullptr);
2136 inline void eval_abs(gmp_int& result, const gmp_int& val)
2138 mpz_abs(result.data(), val.data());
2141 inline void eval_gcd(gmp_int& result, const gmp_int& a, const gmp_int& b)
2143 mpz_gcd(result.data(), a.data(), b.data());
2145 inline void eval_lcm(gmp_int& result, const gmp_int& a, const gmp_int& b)
2147 mpz_lcm(result.data(), a.data(), b.data());
2150 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)
2152 mpz_gcd_ui(result.data(), a.data(), b);
2155 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)
2157 mpz_lcm_ui(result.data(), a.data(), b);
2160 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)
2162 mpz_gcd_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b));
2165 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)
2167 mpz_lcm_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b));
2170 inline void eval_integer_sqrt(gmp_int& s, gmp_int& r, const gmp_int& x)
2172 mpz_sqrtrem(s.data(), r.data(), x.data());
2175 inline std::size_t eval_lsb(const gmp_int& val)
2177 int c = eval_get_sign(val);
2180 BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
2184 BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
2186 return static_cast<unsigned>(mpz_scan1(val.data(), 0));
2189 inline std::size_t eval_msb(const gmp_int& val)
2191 int c = eval_get_sign(val);
2194 BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
2198 BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
2200 return static_cast<unsigned>(mpz_sizeinbase(val.data(), 2) - 1);
2203 inline bool eval_bit_test(const gmp_int& val, std::size_t index)
2205 return mpz_tstbit(val.data(), index) ? true : false;
2208 inline void eval_bit_set(gmp_int& val, std::size_t index)
2210 mpz_setbit(val.data(), index);
2213 inline void eval_bit_unset(gmp_int& val, std::size_t index)
2215 mpz_clrbit(val.data(), index);
2218 inline void eval_bit_flip(gmp_int& val, std::size_t index)
2220 mpz_combit(val.data(), index);
2223 inline void eval_qr(const gmp_int& x, const gmp_int& y,
2224 gmp_int& q, gmp_int& r)
2226 mpz_tdiv_qr(q.data(), r.data(), x.data(), y.data());
2229 template <class Integer>
2230 inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val)
2232 #if defined(__MPIR_VERSION) && (__MPIR_VERSION >= 3)
2233 if ((sizeof(Integer) <= sizeof(mpir_ui)) || (val <= (std::numeric_limits<mpir_ui>::max)()))
2235 if ((sizeof(Integer) <= sizeof(long)) || (val <= (std::numeric_limits<unsigned long>::max)()))
2238 return static_cast<Integer>(mpz_tdiv_ui(x.data(), val));
2242 return default_ops::eval_integer_modulus(x, val);
2245 template <class Integer>
2246 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)
2248 return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val));
2250 inline void eval_powm(gmp_int& result, const gmp_int& base, const gmp_int& p, const gmp_int& m)
2252 if (eval_get_sign(p) < 0)
2254 BOOST_MP_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
2256 mpz_powm(result.data(), base.data(), p.data(), m.data());
2259 template <class Integer>
2260 inline typename std::enable_if<
2261 boost::multiprecision::detail::is_unsigned<Integer>::value && (sizeof(Integer) <= sizeof(unsigned long))>::type
2262 eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m)
2264 mpz_powm_ui(result.data(), base.data(), p, m.data());
2266 template <class Integer>
2267 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
2268 eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m)
2272 BOOST_MP_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
2274 mpz_powm_ui(result.data(), base.data(), p, m.data());
2277 inline std::size_t hash_value(const gmp_int& val)
2279 // We should really use mpz_limbs_read here, but that's unsupported on older versions:
2280 std::size_t result = 0;
2281 for (int i = 0; i < std::abs(val.data()[0]._mp_size); ++i)
2282 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_d[i]);
2283 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_size);
2287 struct gmp_rational;
2288 void eval_add(gmp_rational& t, const gmp_rational& o);
2292 #ifdef BOOST_HAS_LONG_LONG
2293 using signed_types = std::tuple<long, long long> ;
2294 using unsigned_types = std::tuple<unsigned long, unsigned long long>;
2296 using signed_types = std::tuple<long> ;
2297 using unsigned_types = std::tuple<unsigned long>;
2299 using float_types = std::tuple<double, long double>;
2303 mpq_init(this->m_data);
2305 gmp_rational(const gmp_rational& o)
2308 if (o.m_data[0]._mp_num._mp_d)
2309 mpq_set(m_data, o.m_data);
2311 gmp_rational(const gmp_int& o)
2313 mpz_init_set(&m_data[0]._mp_num, o.data());
2314 mpz_init_set_ui(&m_data[0]._mp_den, 1u);
2316 gmp_rational(long i)
2318 mpz_init_set_si(&m_data[0]._mp_num, i);
2319 mpz_init_set_ui(&m_data[0]._mp_den, 1u);
2321 gmp_rational(unsigned long ui)
2323 mpz_init_set_ui(&m_data[0]._mp_num, ui);
2324 mpz_init_set_ui(&m_data[0]._mp_den, 1u);
2326 // 2-arg constructors:
2327 template <class T, class U>
2328 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)
2331 m_data[0]._mp_num = i.data()[0];
2332 m_data[0]._mp_den = j.data()[0];
2333 mpq_canonicalize(m_data);
2334 i.data()[0]._mp_d = nullptr;
2335 j.data()[0]._mp_d = nullptr;
2338 gmp_rational(const gmp_int& a, const U& b, typename std::enable_if<std::is_constructible<gmp_int, U>::value>::type* = nullptr)
2341 mpz_init_set(&m_data[0]._mp_num, a.data());
2342 m_data[0]._mp_den = j.data()[0];
2343 if (boost::multiprecision::detail::unsigned_abs(b) > 1)
2344 mpq_canonicalize(m_data);
2345 j.data()[0]._mp_d = nullptr;
2348 gmp_rational(gmp_int&& a, const U& b, typename std::enable_if<std::is_constructible<gmp_int, U>::value>::type* = nullptr)
2351 m_data[0]._mp_num = a.data()[0];
2352 m_data[0]._mp_den = j.data()[0];
2353 if (boost::multiprecision::detail::unsigned_abs(b) > 1)
2354 mpq_canonicalize(m_data);
2355 a.data()[0]._mp_d = nullptr;
2356 j.data()[0]._mp_d = nullptr;
2359 gmp_rational(const T& a, const gmp_int& b, typename std::enable_if<std::is_constructible<gmp_int, T>::value>::type* = nullptr)
2362 m_data[0]._mp_num = i.data()[0];
2363 mpz_init_set(&m_data[0]._mp_den, b.data());
2364 if(boost::multiprecision::detail::unsigned_abs(a) > 1)
2365 mpq_canonicalize(m_data);
2366 i.data()[0]._mp_d = nullptr;
2369 gmp_rational(const T& a, gmp_int&& b, typename std::enable_if<std::is_constructible<gmp_int, T>::value>::type* = nullptr)
2372 m_data[0]._mp_num = i.data()[0];
2373 m_data[0]._mp_den = b.data()[0];
2374 if(boost::multiprecision::detail::unsigned_abs(a) > 1)
2375 mpq_canonicalize(m_data);
2376 i.data()[0]._mp_d = nullptr;
2377 b.data()[0]._mp_d = nullptr;
2379 gmp_rational(const gmp_int& a, const gmp_int& b)
2381 mpz_init_set(&m_data[0]._mp_num, a.data());
2382 mpz_init_set(&m_data[0]._mp_den, b.data());
2383 mpq_canonicalize(m_data);
2385 gmp_rational(const gmp_int& a, gmp_int&& b)
2387 mpz_init_set(&m_data[0]._mp_num, a.data());
2388 m_data[0]._mp_den = b.data()[0];
2389 mpq_canonicalize(m_data);
2390 b.data()[0]._mp_d = nullptr;
2392 gmp_rational(gmp_int&& a, const gmp_int& b)
2394 m_data[0]._mp_num = a.data()[0];
2395 mpz_init_set(&m_data[0]._mp_den, b.data());
2396 mpq_canonicalize(m_data);
2397 a.data()[0]._mp_d = nullptr;
2399 gmp_rational(gmp_int&& a, gmp_int&& b)
2401 m_data[0]._mp_num = a.data()[0];
2402 m_data[0]._mp_den = b.data()[0];
2403 mpq_canonicalize(m_data);
2404 a.data()[0]._mp_d = nullptr;
2405 b.data()[0]._mp_d = nullptr;
2408 gmp_rational(gmp_rational&& o) noexcept
2410 m_data[0] = o.m_data[0];
2411 o.m_data[0]._mp_num._mp_d = 0;
2412 o.m_data[0]._mp_den._mp_d = 0;
2414 gmp_rational(const mpq_t o)
2419 gmp_rational(const mpz_t o)
2422 mpq_set_z(m_data, o);
2424 gmp_rational& operator=(const gmp_rational& o)
2426 if (m_data[0]._mp_den._mp_d == 0)
2428 mpq_set(m_data, o.m_data);
2432 gmp_rational& operator=(gmp_rational&& o) noexcept
2434 mpq_swap(m_data, o.m_data);
2437 #ifdef BOOST_HAS_LONG_LONG
2438 #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX)
2439 gmp_rational& operator=(unsigned long long i)
2441 *this = static_cast<unsigned long>(i);
2445 gmp_rational& operator=(unsigned long long i)
2447 if (m_data[0]._mp_den._mp_d == 0)
2451 mpq_set_z(m_data, zi.data());
2454 gmp_rational& operator=(long long i)
2456 if (m_data[0]._mp_den._mp_d == 0)
2459 *this = boost::multiprecision::detail::unsigned_abs(i);
2461 mpq_neg(m_data, m_data);
2466 gmp_rational& operator=(unsigned long i)
2468 if (m_data[0]._mp_den._mp_d == 0)
2470 mpq_set_ui(m_data, i, 1);
2473 gmp_rational& operator=(long i)
2475 if (m_data[0]._mp_den._mp_d == 0)
2477 mpq_set_si(m_data, i, 1);
2480 gmp_rational& operator=(double d)
2482 if (m_data[0]._mp_den._mp_d == 0)
2484 mpq_set_d(m_data, d);
2488 gmp_rational& assign_float(F a)
2490 using default_ops::eval_add;
2491 using default_ops::eval_subtract;
2492 BOOST_MP_FLOAT128_USING using std::floor; using std::frexp; using std::ldexp;
2494 if (m_data[0]._mp_den._mp_d == 0)
2499 mpq_set_si(m_data, 0, 1);
2505 mpq_set_si(m_data, 1, 1);
2509 BOOST_MP_ASSERT(!BOOST_MP_ISINF(a));
2510 BOOST_MP_ASSERT(!BOOST_MP_ISNAN(a));
2514 mpq_set_ui(m_data, 0, 1);
2515 mpq_set_ui(m_data, 0u, 1);
2520 constexpr const int shift = std::numeric_limits<int>::digits - 1;
2524 // extract int sized bits from f:
2525 f = ldexp(f, shift);
2528 mpq_mul_2exp(m_data, m_data, shift);
2529 t = static_cast<long>(term);
2534 mpq_mul_2exp(m_data, m_data, e);
2536 mpq_div_2exp(m_data, m_data, -e);
2539 gmp_rational& operator=(long double a)
2541 return assign_float(a);
2543 #ifdef BOOST_HAS_FLOAT128
2544 gmp_rational& operator=(float128_type a)
2546 return assign_float(a);
2549 #ifdef BOOST_HAS_INT128
2550 gmp_rational& operator=(uint128_type i)
2556 gmp_rational& operator=(int128_type i)
2563 gmp_rational& operator=(const char* s)
2565 if (m_data[0]._mp_den._mp_d == 0)
2567 if (0 != mpq_set_str(m_data, s, 10))
2568 BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid rational number.")));
2571 gmp_rational& operator=(const gmp_int& o)
2573 if (m_data[0]._mp_den._mp_d == 0)
2575 mpq_set_z(m_data, o.data());
2578 gmp_rational& operator=(const mpq_t o)
2580 if (m_data[0]._mp_den._mp_d == 0)
2585 gmp_rational& operator=(const mpz_t o)
2587 if (m_data[0]._mp_den._mp_d == 0)
2589 mpq_set_z(m_data, o);
2592 void swap(gmp_rational& o)
2594 mpq_swap(m_data, o.m_data);
2596 std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags /*f*/) const
2598 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2599 // TODO make a better job of this including handling of f!!
2600 void* (*alloc_func_ptr)(size_t);
2601 void* (*realloc_func_ptr)(void*, size_t, size_t);
2602 void (*free_func_ptr)(void*, size_t);
2603 const char* ps = mpq_get_str(0, 10, m_data);
2605 mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
2606 (*free_func_ptr)((void*)ps, std::strlen(ps) + 1);
2611 if (m_data[0]._mp_num._mp_d || m_data[0]._mp_den._mp_d)
2616 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2617 mpq_neg(m_data, m_data);
2619 int compare(const gmp_rational& o) const
2621 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d && o.m_data[0]._mp_num._mp_d);
2622 return mpq_cmp(m_data, o.m_data);
2625 int compare(V v) const
2631 int compare(unsigned long v) const
2633 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2634 return mpq_cmp_ui(m_data, v, 1);
2636 int compare(long v) const
2638 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2639 return mpq_cmp_si(m_data, v, 1);
2643 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2646 const mpq_t& data() const
2648 BOOST_MP_ASSERT(m_data[0]._mp_num._mp_d);
2656 inline bool eval_is_zero(const gmp_rational& val)
2658 return mpq_sgn(val.data()) == 0;
2661 inline bool eval_eq(gmp_rational& a, const T& b)
2663 return a.compare(b) == 0;
2666 inline bool eval_lt(gmp_rational& a, const T& b)
2668 return a.compare(b) < 0;
2671 inline bool eval_gt(gmp_rational& a, const T& b)
2673 return a.compare(b) > 0;
2676 inline void eval_add(gmp_rational& t, const gmp_rational& o)
2678 mpq_add(t.data(), t.data(), o.data());
2680 inline void eval_subtract(gmp_rational& t, const gmp_rational& o)
2682 mpq_sub(t.data(), t.data(), o.data());
2684 inline void eval_multiply(gmp_rational& t, const gmp_rational& o)
2686 mpq_mul(t.data(), t.data(), o.data());
2688 inline void eval_divide(gmp_rational& t, const gmp_rational& o)
2690 if (eval_is_zero(o))
2691 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2692 mpq_div(t.data(), t.data(), o.data());
2694 inline void eval_add(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2696 mpq_add(t.data(), p.data(), o.data());
2698 inline void eval_subtract(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2700 mpq_sub(t.data(), p.data(), o.data());
2702 inline void eval_multiply(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2704 mpq_mul(t.data(), p.data(), o.data());
2706 inline void eval_divide(gmp_rational& t, const gmp_rational& p, const gmp_rational& o)
2708 if (eval_is_zero(o))
2709 BOOST_MP_THROW_EXCEPTION(std::overflow_error("Division by zero."));
2710 mpq_div(t.data(), p.data(), o.data());
2713 // operator with scalars:
2715 inline void eval_add(gmp_rational& result, gmp_rational const& a, gmp_int const& b)
2717 // we allow result and a to be the same object here:
2720 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2721 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2723 mpz_addmul(mpq_numref(result.data()), mpq_denref(a.data()), b.data());
2724 // no need to normalize, there can be no common divisor as long as a is already normalized.
2726 inline void eval_add(gmp_rational& result, gmp_rational const& a, unsigned long b)
2728 // we allow result and a to be the same object here:
2731 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2732 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2734 mpz_addmul_ui(mpq_numref(result.data()), mpq_denref(a.data()), b);
2735 // no need to normalize, there can be no common divisor as long as a is already normalized.
2737 inline void eval_add(gmp_rational& result, gmp_rational const& a, long b)
2739 // we allow result and a to be the same object here:
2742 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2743 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2746 mpz_addmul_ui(mpq_numref(result.data()), mpq_denref(a.data()), b);
2748 mpz_submul_ui(mpq_numref(result.data()), mpq_denref(a.data()), boost::multiprecision::detail::unsigned_abs(b));
2749 // no need to normalize, there can be no common divisor as long as a is already normalized.
2752 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)
2756 eval_add(result, a, t);
2759 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)
2761 eval_add(result, a, b);
2764 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_add(gmp_rational& result, const T& b)
2766 eval_add(result, result, b);
2768 inline void eval_subtract(gmp_rational& result, gmp_rational const& a, gmp_int const& b)
2770 // we allow result and a to be the same object here:
2773 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2774 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2776 mpz_submul(mpq_numref(result.data()), mpq_denref(a.data()), b.data());
2777 // no need to normalize, there can be no common divisor as long as a is already normalized.
2779 inline void eval_subtract(gmp_rational& result, gmp_rational const& a, unsigned long b)
2781 // we allow result and a to be the same object here:
2784 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2785 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2787 mpz_submul_ui(mpq_numref(result.data()), mpq_denref(a.data()), b);
2788 // no need to normalize, there can be no common divisor as long as a is already normalized.
2790 inline void eval_subtract(gmp_rational& result, gmp_rational const& a, long b)
2792 // we allow result and a to be the same object here:
2795 mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
2796 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2799 mpz_submul_ui(mpq_numref(result.data()), mpq_denref(a.data()), b);
2801 mpz_addmul_ui(mpq_numref(result.data()), mpq_denref(a.data()), boost::multiprecision::detail::unsigned_abs(b));
2802 // no need to normalize, there can be no common divisor as long as a is already normalized.
2805 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)
2809 eval_subtract(result, a, t);
2812 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)
2814 eval_subtract(result, a, b);
2818 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_subtract(gmp_rational& result, const T& b)
2820 eval_subtract(result, result, b);
2823 inline void eval_multiply(gmp_rational& result, gmp_rational const& a, gmp_int const& b)
2826 mpz_gcd(g.data(), mpq_denref(a.data()), b.data());
2827 if (!mpz_fits_uint_p(g.data()) || (mpz_get_ui(g.data()) != 1))
2829 // We get here if the gcd is not unity, this is true if the number is
2830 // too large for an unsigned long, or if we get an unsigned long and check against 1.
2831 eval_divide(t, b, g);
2832 mpz_mul(mpq_numref(result.data()), t.data(), mpq_numref(a.data()));
2833 mpz_divexact(mpq_denref(result.data()), mpq_denref(a.data()), g.data());
2838 mpz_mul(mpq_numref(result.data()), mpq_numref(a.data()), b.data());
2840 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2843 inline void eval_multiply(gmp_rational& result, gmp_rational const& a, unsigned long b)
2847 mpq_set_ui(result.data(), b, 1);
2850 if (mpz_sgn(mpq_numref(a.data())) == 0)
2855 unsigned long g = mpz_gcd_ui(nullptr, mpq_denref(a.data()), b);
2860 mpz_mul_ui(mpq_numref(result.data()), mpq_numref(a.data()), b);
2861 mpz_divexact_ui(mpq_denref(result.data()), mpq_denref(a.data()), g);
2865 mpz_mul_ui(mpq_numref(result.data()), mpq_numref(a.data()), b);
2867 mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
2870 inline void eval_multiply(gmp_rational& result, gmp_rational const& a, long b)
2872 eval_multiply(result, a, boost::multiprecision::detail::unsigned_abs(b));
2877 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)
2881 eval_multiply(result, a, t);
2884 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)
2886 eval_multiply(result, a, b);
2889 inline typename std::enable_if<boost::multiprecision::detail::is_integral<T>::value>::type eval_multiply(gmp_rational& result, const T& b)
2891 eval_multiply(result, result, b);
2894 inline int eval_get_sign(const gmp_rational& val)
2896 return mpq_sgn(val.data());
2899 inline typename std::enable_if<number_category<R>::value == number_kind_floating_point>::type eval_convert_to(R* result, const gmp_rational& backend)
2902 // The generic conversion is as good as anything we can write here:
2904 // This does not round correctly:
2906 //*result = mpq_get_d(val.data());
2910 ::boost::multiprecision::detail::generic_convert_rational_to_float(*result, backend);
2912 #ifdef BOOST_HAS_FLOAT128
2913 inline void eval_convert_to(float128_type* result, const gmp_rational& val)
2915 using default_ops::eval_convert_to;
2918 float128_type fn, fd;
2919 mpz_set(n.data(), mpq_numref(val.data()));
2920 mpz_set(d.data(), mpq_denref(val.data()));
2922 eval_convert_to(&fn, n);
2923 eval_convert_to(&fd, d);
2930 inline typename std::enable_if<number_category<R>::value == number_kind_integer>::type eval_convert_to(R* result, const gmp_rational& backend)
2932 gmp_int n(mpq_numref(backend.data()));
2933 gmp_int d(mpq_denref(backend.data()));
2934 using default_ops::eval_divide;
2936 using default_ops::eval_convert_to;
2937 eval_convert_to(result, n);
2940 inline void eval_abs(gmp_rational& result, const gmp_rational& val)
2942 mpq_abs(result.data(), val.data());
2945 inline void assign_components(gmp_rational& result, unsigned long v1, unsigned long v2)
2947 mpq_set_ui(result.data(), v1, v2);
2948 mpq_canonicalize(result.data());
2950 inline void assign_components(gmp_rational& result, long v1, long v2)
2952 mpq_set_si(result.data(), v1, v2);
2953 mpq_canonicalize(result.data());
2955 inline void assign_components(gmp_rational& result, gmp_int const& v1, gmp_int const& v2)
2957 mpz_set(mpq_numref(result.data()), v1.data());
2958 mpz_set(mpq_denref(result.data()), v2.data());
2959 mpq_canonicalize(result.data());
2961 template <class T, class U>
2962 void assign_components(gmp_rational& result, const T& a, const U& b)
2967 std::swap(result.data()[0]._mp_num, x.data()[0]);
2968 std::swap(result.data()[0]._mp_den, y.data()[0]);
2969 mpq_canonicalize(result.data());
2972 void assign_components(gmp_rational& result, const gmp_int& a, const U& b)
2976 mpz_set(&result.data()[0]._mp_num, a.data());
2977 std::swap(result.data()[0]._mp_den, y.data()[0]);
2978 mpq_canonicalize(result.data());
2981 void assign_components(gmp_rational& result, const T& a, const gmp_int& b)
2985 std::swap(result.data()[0]._mp_num, x.data()[0]);
2986 mpz_set(&result.data()[0]._mp_den, b.data());
2987 mpq_canonicalize(result.data());
2991 inline std::size_t hash_value(const gmp_rational& val)
2993 std::size_t result = 0;
2994 for (int i = 0; i < std::abs(val.data()[0]._mp_num._mp_size); ++i)
2995 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_num._mp_d[i]);
2996 for (int i = 0; i < std::abs(val.data()[0]._mp_den._mp_size); ++i)
2997 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_den._mp_d[i]);
2998 boost::multiprecision::detail::hash_combine(result, val.data()[0]._mp_num._mp_size);
3003 // Some useful helpers:
3005 inline std::size_t used_gmp_int_bits(const gmp_int& val)
3007 return eval_msb(val) - eval_lsb(val) + 1;
3009 inline std::size_t used_gmp_rational_bits(const gmp_rational& val)
3011 unsigned d2_d = static_cast<unsigned>(mpz_sizeinbase(mpq_denref(val.data()), 2) - mpz_scan1(mpq_denref(val.data()), 0));
3012 unsigned d2_n = static_cast<unsigned>(mpz_sizeinbase(mpq_numref(val.data()), 2) - mpz_scan1(mpq_numref(val.data()), 0));
3013 return (std::max)(d2_d, d2_n);
3017 // Some member functions that are dependent upon previous code go here:
3019 template <unsigned Digits10>
3020 template <unsigned D>
3021 inline gmp_float<Digits10>::gmp_float(const gmp_float<D>& o, typename std::enable_if<D <= Digits10>::type*)
3023 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3024 mpf_set(this->m_data, o.data());
3026 template <unsigned Digits10>
3027 template <unsigned D>
3028 inline gmp_float<Digits10>::gmp_float(const gmp_float<D>& o, typename std::enable_if< !(D <= Digits10)>::type*)
3030 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3031 mpf_set(this->m_data, o.data());
3033 template <unsigned Digits10>
3034 inline gmp_float<Digits10>::gmp_float(const gmp_int& o)
3036 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3037 mpf_set_z(this->data(), o.data());
3039 template <unsigned Digits10>
3040 inline gmp_float<Digits10>::gmp_float(const gmp_rational& o)
3042 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3043 mpf_set_q(this->data(), o.data());
3045 template <unsigned Digits10>
3046 template <unsigned D>
3047 inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_float<D>& o)
3049 if (this->m_data[0]._mp_d == 0)
3050 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3051 mpf_set(this->m_data, o.data());
3054 template <unsigned Digits10>
3055 inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_int& o)
3057 if (this->m_data[0]._mp_d == 0)
3058 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3059 mpf_set_z(this->data(), o.data());
3062 template <unsigned Digits10>
3063 inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_rational& o)
3065 if (this->m_data[0]._mp_d == 0)
3066 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision()));
3067 mpf_set_q(this->data(), o.data());
3070 inline gmp_float<0>::gmp_float(const gmp_int& o) : requested_precision(get_default_precision())
3072 if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3074 std::size_t d2 = used_gmp_int_bits(o);
3075 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(d2);
3076 if (d10 > requested_precision)
3077 requested_precision = static_cast<unsigned>(d10);
3079 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
3080 mpf_set_z(this->data(), o.data());
3082 inline gmp_float<0>::gmp_float(const gmp_rational& o) : requested_precision(get_default_precision())
3084 if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3086 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(o));
3087 if (d10 > requested_precision)
3088 requested_precision = static_cast<unsigned>(d10);
3090 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
3091 mpf_set_q(this->data(), o.data());
3093 inline gmp_float<0>& gmp_float<0>::operator=(const gmp_int& o)
3095 if (this->m_data[0]._mp_d == 0)
3097 requested_precision = this->get_default_precision();
3098 if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3100 std::size_t d2 = used_gmp_int_bits(o);
3101 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(d2);
3102 if (d10 > requested_precision)
3103 requested_precision = static_cast<unsigned>(d10);
3105 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
3107 else if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3109 std::size_t d2 = used_gmp_int_bits(o);
3110 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(d2);
3111 if (d10 > requested_precision)
3112 this->precision(static_cast<unsigned>(d10));
3114 mpf_set_z(this->data(), o.data());
3117 inline gmp_float<0>& gmp_float<0>::operator=(const gmp_rational& o)
3119 if (this->m_data[0]._mp_d == 0)
3121 requested_precision = this->get_default_precision();
3122 if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3124 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(o));
3125 if (d10 > requested_precision)
3126 requested_precision = static_cast<unsigned>(d10);
3128 mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision));
3130 else if (thread_default_variable_precision_options() >= variable_precision_options::preserve_all_precision)
3132 std::size_t d10 = 1 + multiprecision::detail::digits2_2_10(used_gmp_rational_bits(o));
3133 if (d10 > requested_precision)
3134 this->precision(static_cast<unsigned>(d10));
3136 mpf_set_q(this->data(), o.data());
3139 inline gmp_int::gmp_int(const gmp_rational& o)
3141 mpz_init(this->m_data);
3142 mpz_set_q(this->m_data, o.data());
3144 inline gmp_int& gmp_int::operator=(const gmp_rational& o)
3146 if (this->m_data[0]._mp_d == 0)
3147 mpz_init(this->m_data);
3148 mpz_set_q(this->m_data, o.data());
3152 } //namespace backends
3154 using boost::multiprecision::backends::gmp_float;
3155 using boost::multiprecision::backends::gmp_int;
3156 using boost::multiprecision::backends::gmp_rational;
3158 template <expression_template_option ExpressionTemplates>
3159 struct component_type<number<gmp_rational, ExpressionTemplates> >
3161 using type = number<gmp_int, ExpressionTemplates>;
3164 template <expression_template_option ET>
3165 inline number<gmp_int, ET> numerator(const number<gmp_rational, ET>& val)
3167 number<gmp_int, ET> result;
3168 mpz_set(result.backend().data(), (mpq_numref(val.backend().data())));
3171 template <expression_template_option ET>
3172 inline number<gmp_int, ET> denominator(const number<gmp_rational, ET>& val)
3174 number<gmp_int, ET> result;
3175 mpz_set(result.backend().data(), (mpq_denref(val.backend().data())));
3182 struct digits2<number<gmp_float<0>, et_on> >
3186 return multiprecision::detail::digits10_2_2(gmp_float<0>::thread_default_precision());
3191 struct digits2<number<gmp_float<0>, et_off> >
3195 return multiprecision::detail::digits10_2_2(gmp_float<0>::thread_default_precision());
3200 struct digits2<number<debug_adaptor<gmp_float<0> >, et_on> >
3204 return multiprecision::detail::digits10_2_2(gmp_float<0>::thread_default_precision());
3209 struct digits2<number<debug_adaptor<gmp_float<0> >, et_off> >
3213 return multiprecision::detail::digits10_2_2(gmp_float<0>::thread_default_precision());
3217 template <unsigned Digits10>
3218 struct transcendental_reduction_type<boost::multiprecision::backends::gmp_float<Digits10> >
3221 // The type used for trigonometric reduction needs 3 times the precision of the base type.
3222 // This is double the precision of the original type, plus the largest exponent supported.
3223 // As a practical measure the largest argument supported is 1/eps, as supporting larger
3224 // arguments requires the division of argument by PI/2 to also be done at higher precision,
3225 // otherwise the result (an integer) can not be represented exactly.
3227 // See ARGUMENT REDUCTION FOR HUGE ARGUMENTS. K C Ng.
3229 using type = boost::multiprecision::backends::gmp_float<Digits10 * 3>;
3233 } // namespace detail
3236 struct number_category<detail::canonical<mpz_t, gmp_int>::type> : public std::integral_constant<int, number_kind_integer>
3239 struct number_category<detail::canonical<mpq_t, gmp_rational>::type> : public std::integral_constant<int, number_kind_rational>
3242 struct number_category<detail::canonical<mpf_t, gmp_float<0> >::type> : public std::integral_constant<int, number_kind_floating_point>
3247 struct is_variable_precision<backends::gmp_float<0> > : public std::integral_constant<bool, true>
3249 } // namespace detail
3251 using mpf_float_50 = number<gmp_float<50> > ;
3252 using mpf_float_100 = number<gmp_float<100> > ;
3253 using mpf_float_500 = number<gmp_float<500> > ;
3254 using mpf_float_1000 = number<gmp_float<1000> >;
3255 using mpf_float = number<gmp_float<0> > ;
3256 using mpz_int = number<gmp_int> ;
3257 using mpq_rational = number<gmp_rational> ;
3259 } // namespace multiprecision
3261 namespace math { namespace tools {
3263 #ifndef BOOST_MP_MATH_AVAILABLE
3265 template <typename T>
3266 inline int digits();
3268 template <typename T>
3269 inline T max_value();
3271 template <typename T>
3272 inline T min_value();
3274 #endif // BOOST_MP_MATH_AVAILABLE
3276 inline void set_output_precision(const boost::multiprecision::mpf_float& val, std::ostream& os)
3278 os << std::setprecision(val.precision());
3282 inline int digits<boost::multiprecision::mpf_float>()
3283 #ifdef BOOST_MATH_NOEXCEPT
3287 return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::thread_default_precision());
3290 inline int digits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
3291 #ifdef BOOST_MATH_NOEXCEPT
3295 return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::thread_default_precision());
3299 inline boost::multiprecision::mpf_float
3300 max_value<boost::multiprecision::mpf_float>()
3302 boost::multiprecision::mpf_float result(0.5);
3303 mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3308 inline boost::multiprecision::mpf_float
3309 min_value<boost::multiprecision::mpf_float>()
3311 boost::multiprecision::mpf_float result(0.5);
3312 mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3317 inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off>
3318 max_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
3320 boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5);
3321 mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3326 inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off>
3327 min_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >()
3329 boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5);
3330 mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3335 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
3336 #ifdef BOOST_MATH_NOEXCEPT
3340 return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::thread_default_precision());
3343 inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
3344 #ifdef BOOST_MATH_NOEXCEPT
3348 return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::thread_default_precision());
3352 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >
3353 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
3355 return max_value<boost::multiprecision::mpf_float>().backend();
3359 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >
3360 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >()
3362 return min_value<boost::multiprecision::mpf_float>().backend();
3366 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off>
3367 max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
3369 return max_value<boost::multiprecision::mpf_float>().backend();
3373 inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off>
3374 min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >()
3376 return min_value<boost::multiprecision::mpf_float>().backend();
3379 }} // namespace math::tools
3381 } // namespace boost
3386 // numeric_limits [partial] specializations for the types declared in this header:
3388 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3389 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >
3391 using number_type = boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates>;
3394 // min and max values chosen so as to not cause segfaults when calling
3395 // mpf_get_str on 64-bit Linux builds. Possibly we could use larger
3396 // exponent values elsewhere.
3398 static number_type calc_min()
3400 number_type result(1);
3401 mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3404 static number_type calc_max()
3406 number_type result(1);
3407 mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1);
3410 static number_type calc_epsilon()
3412 number_type result(1);
3413 mpf_div_2exp(result.backend().data(), result.backend().data(), std::numeric_limits<number_type>::digits - 1);
3419 static constexpr bool is_specialized = true;
3420 static number_type(min)()
3422 // rely on C++11 thread safe initialization of statics:
3423 static const number_type value{calc_min()};
3426 static number_type(max)()
3428 static number_type value{calc_max()};
3431 static constexpr number_type lowest()
3435 static constexpr int digits = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301L ? 2 : 1));
3436 static constexpr int digits10 = Digits10;
3437 // Have to allow for a possible extra limb inside the gmp data structure:
3438 static constexpr int max_digits10 = Digits10 + 3 + ((GMP_LIMB_BITS * 301L) / 1000L);
3439 static constexpr bool is_signed = true;
3440 static constexpr bool is_integer = false;
3441 static constexpr bool is_exact = false;
3442 static constexpr int radix = 2;
3443 static number_type epsilon()
3445 static const number_type value{calc_epsilon()};
3448 // What value should this be????
3449 static number_type round_error()
3453 static constexpr long min_exponent = LONG_MIN;
3454 static constexpr long min_exponent10 = (LONG_MIN / 1000) * 301L;
3455 static constexpr long max_exponent = LONG_MAX;
3456 static constexpr long max_exponent10 = (LONG_MAX / 1000) * 301L;
3457 static constexpr bool has_infinity = false;
3458 static constexpr bool has_quiet_NaN = false;
3459 static constexpr bool has_signaling_NaN = false;
3460 static constexpr float_denorm_style has_denorm = denorm_absent;
3461 static constexpr bool has_denorm_loss = false;
3462 static constexpr number_type infinity() { return number_type(); }
3463 static constexpr number_type quiet_NaN() { return number_type(); }
3464 static constexpr number_type signaling_NaN() { return number_type(); }
3465 static constexpr number_type denorm_min() { return number_type(); }
3466 static constexpr bool is_iec559 = false;
3467 static constexpr bool is_bounded = true;
3468 static constexpr bool is_modulo = false;
3469 static constexpr bool traps = true;
3470 static constexpr bool tinyness_before = false;
3471 static constexpr float_round_style round_style = round_indeterminate;
3474 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3475 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::digits;
3476 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3477 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::digits10;
3478 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3479 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_digits10;
3480 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3481 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_signed;
3482 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3483 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_integer;
3484 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3485 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_exact;
3486 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3487 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::radix;
3488 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3489 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::min_exponent;
3490 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3491 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::min_exponent10;
3492 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3493 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_exponent;
3494 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3495 constexpr long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_exponent10;
3496 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3497 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_infinity;
3498 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3499 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_quiet_NaN;
3500 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3501 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_signaling_NaN;
3502 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3503 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_denorm;
3504 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3505 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_denorm_loss;
3506 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3507 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_iec559;
3508 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3509 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_bounded;
3510 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3511 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_modulo;
3512 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3513 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::traps;
3514 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3515 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::tinyness_before;
3516 template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates>
3517 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::round_style;
3519 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3520 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >
3522 using number_type = boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates>;
3525 static constexpr bool is_specialized = false;
3526 static number_type(min)() { return number_type(); }
3527 static number_type(max)() { return number_type(); }
3528 static number_type lowest() { return number_type(); }
3529 static constexpr int digits = 0;
3530 static constexpr int digits10 = 0;
3531 static constexpr int max_digits10 = 0;
3532 static constexpr bool is_signed = false;
3533 static constexpr bool is_integer = false;
3534 static constexpr bool is_exact = false;
3535 static constexpr int radix = 0;
3536 static number_type epsilon() { return number_type(); }
3537 static number_type round_error() { return number_type(); }
3538 static constexpr int min_exponent = 0;
3539 static constexpr int min_exponent10 = 0;
3540 static constexpr int max_exponent = 0;
3541 static constexpr int max_exponent10 = 0;
3542 static constexpr bool has_infinity = false;
3543 static constexpr bool has_quiet_NaN = false;
3544 static constexpr bool has_signaling_NaN = false;
3545 static constexpr float_denorm_style has_denorm = denorm_absent;
3546 static constexpr bool has_denorm_loss = false;
3547 static number_type infinity() { return number_type(); }
3548 static number_type quiet_NaN() { return number_type(); }
3549 static number_type signaling_NaN() { return number_type(); }
3550 static number_type denorm_min() { return number_type(); }
3551 static constexpr bool is_iec559 = false;
3552 static constexpr bool is_bounded = false;
3553 static constexpr bool is_modulo = false;
3554 static constexpr bool traps = false;
3555 static constexpr bool tinyness_before = false;
3556 static constexpr float_round_style round_style = round_indeterminate;
3559 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3560 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits;
3561 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3562 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits10;
3563 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3564 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_digits10;
3565 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3566 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_signed;
3567 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3568 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_integer;
3569 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3570 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_exact;
3571 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3572 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::radix;
3573 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3574 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent;
3575 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3576 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent10;
3577 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3578 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent;
3579 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3580 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent10;
3581 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3582 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_infinity;
3583 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3584 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_quiet_NaN;
3585 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3586 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_signaling_NaN;
3587 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3588 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm;
3589 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3590 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm_loss;
3591 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3592 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_iec559;
3593 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3594 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_bounded;
3595 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3596 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_modulo;
3597 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3598 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::traps;
3599 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3600 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::tinyness_before;
3601 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3602 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::round_style;
3604 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3605 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >
3607 using number_type = boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates>;
3610 static constexpr bool is_specialized = true;
3612 // Largest and smallest numbers are bounded only by available memory, set
3615 static number_type(min)()
3617 return number_type();
3619 static number_type(max)()
3621 return number_type();
3623 static number_type lowest() { return (min)(); }
3624 static constexpr int digits = INT_MAX;
3625 static constexpr int digits10 = (INT_MAX / 1000) * 301L;
3626 static constexpr int max_digits10 = digits10 + 3;
3627 static constexpr bool is_signed = true;
3628 static constexpr bool is_integer = true;
3629 static constexpr bool is_exact = true;
3630 static constexpr int radix = 2;
3631 static number_type epsilon() { return number_type(); }
3632 static number_type round_error() { return number_type(); }
3633 static constexpr int min_exponent = 0;
3634 static constexpr int min_exponent10 = 0;
3635 static constexpr int max_exponent = 0;
3636 static constexpr int max_exponent10 = 0;
3637 static constexpr bool has_infinity = false;
3638 static constexpr bool has_quiet_NaN = false;
3639 static constexpr bool has_signaling_NaN = false;
3640 static constexpr float_denorm_style has_denorm = denorm_absent;
3641 static constexpr bool has_denorm_loss = false;
3642 static number_type infinity() { return number_type(); }
3643 static number_type quiet_NaN() { return number_type(); }
3644 static number_type signaling_NaN() { return number_type(); }
3645 static number_type denorm_min() { return number_type(); }
3646 static constexpr bool is_iec559 = false;
3647 static constexpr bool is_bounded = false;
3648 static constexpr bool is_modulo = false;
3649 static constexpr bool traps = false;
3650 static constexpr bool tinyness_before = false;
3651 static constexpr float_round_style round_style = round_toward_zero;
3654 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3655 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits;
3656 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3657 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits10;
3658 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3659 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_digits10;
3660 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3661 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_signed;
3662 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3663 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_integer;
3664 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3665 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_exact;
3666 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3667 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::radix;
3668 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3669 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent;
3670 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3671 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent10;
3672 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3673 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent;
3674 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3675 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent10;
3676 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3677 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_infinity;
3678 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3679 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_quiet_NaN;
3680 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3681 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_signaling_NaN;
3682 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3683 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm;
3684 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3685 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm_loss;
3686 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3687 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_iec559;
3688 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3689 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_bounded;
3690 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3691 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_modulo;
3692 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3693 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::traps;
3694 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3695 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::tinyness_before;
3696 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3697 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::round_style;
3699 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3700 class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >
3702 using number_type = boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates>;
3705 static constexpr bool is_specialized = true;
3707 // Largest and smallest numbers are bounded only by available memory, set
3710 static number_type(min)()
3712 return number_type();
3714 static number_type(max)()
3716 return number_type();
3718 static number_type lowest() { return (min)(); }
3719 // Digits are unbounded, use zero for now:
3720 static constexpr int digits = INT_MAX;
3721 static constexpr int digits10 = (INT_MAX / 1000) * 301L;
3722 static constexpr int max_digits10 = digits10 + 3;
3723 static constexpr bool is_signed = true;
3724 static constexpr bool is_integer = false;
3725 static constexpr bool is_exact = true;
3726 static constexpr int radix = 2;
3727 static number_type epsilon() { return number_type(); }
3728 static number_type round_error() { return number_type(); }
3729 static constexpr int min_exponent = 0;
3730 static constexpr int min_exponent10 = 0;
3731 static constexpr int max_exponent = 0;
3732 static constexpr int max_exponent10 = 0;
3733 static constexpr bool has_infinity = false;
3734 static constexpr bool has_quiet_NaN = false;
3735 static constexpr bool has_signaling_NaN = false;
3736 static constexpr float_denorm_style has_denorm = denorm_absent;
3737 static constexpr bool has_denorm_loss = false;
3738 static number_type infinity() { return number_type(); }
3739 static number_type quiet_NaN() { return number_type(); }
3740 static number_type signaling_NaN() { return number_type(); }
3741 static number_type denorm_min() { return number_type(); }
3742 static constexpr bool is_iec559 = false;
3743 static constexpr bool is_bounded = false;
3744 static constexpr bool is_modulo = false;
3745 static constexpr bool traps = false;
3746 static constexpr bool tinyness_before = false;
3747 static constexpr float_round_style round_style = round_toward_zero;
3750 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3751 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits;
3752 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3753 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits10;
3754 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3755 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_digits10;
3756 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3757 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_signed;
3758 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3759 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_integer;
3760 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3761 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_exact;
3762 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3763 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::radix;
3764 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3765 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent;
3766 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3767 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent10;
3768 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3769 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent;
3770 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3771 constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent10;
3772 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3773 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_infinity;
3774 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3775 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_quiet_NaN;
3776 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3777 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_signaling_NaN;
3778 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3779 constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm;
3780 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3781 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm_loss;
3782 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3783 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_iec559;
3784 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3785 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_bounded;
3786 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3787 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_modulo;
3788 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3789 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::traps;
3790 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3791 constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::tinyness_before;
3792 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3793 constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::round_style;
3796 #pragma warning(pop)
3804 template <class B1, class B2>
3805 struct NumTraitsImp;
3807 template <boost::multiprecision::expression_template_option ExpressionTemplates>
3808 struct NumTraitsImp<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates>, boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >
3810 using self_type = boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates>;
3811 using Real = typename boost::multiprecision::scalar_result_from_possible_complex<self_type>::type;
3812 using NonInteger = self_type; // Not correct but we can't do much better??
3813 using Literal = double;
3814 using Nested = self_type;
3817 IsComplex = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_complex,
3818 IsInteger = boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer,
3822 IsSigned = std::numeric_limits<self_type>::is_specialized ? std::numeric_limits<self_type>::is_signed : true,
3823 RequireInitialization = 1,
3826 static Real highest() noexcept
3828 return boost::math::tools::max_value<Real>();
3830 static Real lowest() noexcept
3832 return boost::math::tools::min_value<Real>();
3834 static int digits() noexcept
3836 return boost::math::tools::digits<Real>();
3838 static int digits10()
3840 return Real::thread_default_precision();
3842 static Real epsilon()
3844 return ldexp(Real(1), 1 - digits());
3846 static Real dummy_precision()
3848 return 1000 * epsilon();
3850 static constexpr long min_exponent() noexcept
3854 static constexpr long max_exponent() noexcept
3858 static Real infinity()
3862 static Real quiet_NaN()