]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Copyright 2011 John Maddock. Distributed under the Boost | |
3 | // Software License, Version 1.0. (See accompanying file | |
4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #ifndef BOOST_MATH_ER_GMP_BACKEND_HPP | |
7 | #define BOOST_MATH_ER_GMP_BACKEND_HPP | |
8 | ||
9 | #include <boost/multiprecision/number.hpp> | |
10 | #include <boost/multiprecision/debug_adaptor.hpp> | |
11 | #include <boost/multiprecision/detail/integer_ops.hpp> | |
12 | #include <boost/multiprecision/detail/big_lanczos.hpp> | |
13 | #include <boost/multiprecision/detail/digits.hpp> | |
f67539c2 | 14 | #include <boost/multiprecision/detail/atomic.hpp> |
7c673cae FG |
15 | #include <boost/math/special_functions/fpclassify.hpp> |
16 | #include <boost/cstdint.hpp> | |
17 | #include <boost/functional/hash_fwd.hpp> | |
18 | // | |
19 | // Some includes we need from Boost.Math, since we rely on that library to provide these functions: | |
20 | // | |
21 | #include <boost/math/special_functions/asinh.hpp> | |
22 | #include <boost/math/special_functions/acosh.hpp> | |
23 | #include <boost/math/special_functions/atanh.hpp> | |
24 | #include <boost/math/special_functions/cbrt.hpp> | |
25 | #include <boost/math/special_functions/expm1.hpp> | |
26 | #include <boost/math/special_functions/gamma.hpp> | |
27 | ||
28 | #ifdef BOOST_MSVC | |
92f5a8d4 TL |
29 | #pragma warning(push) |
30 | #pragma warning(disable : 4127) | |
7c673cae FG |
31 | #endif |
32 | #include <gmp.h> | |
33 | #ifdef BOOST_MSVC | |
92f5a8d4 | 34 | #pragma warning(pop) |
7c673cae FG |
35 | #endif |
36 | ||
37 | #if defined(__MPIR_VERSION) && defined(__MPIR_VERSION_MINOR) && defined(__MPIR_VERSION_PATCHLEVEL) | |
92f5a8d4 | 38 | #define BOOST_MP_MPIR_VERSION (__MPIR_VERSION * 10000 + __MPIR_VERSION_MINOR * 100 + __MPIR_VERSION_PATCHLEVEL) |
7c673cae | 39 | #else |
92f5a8d4 | 40 | #define BOOST_MP_MPIR_VERSION 0 |
7c673cae FG |
41 | #endif |
42 | ||
92f5a8d4 | 43 | #include <cctype> |
7c673cae FG |
44 | #include <cmath> |
45 | #include <limits> | |
46 | #include <climits> | |
47 | ||
92f5a8d4 TL |
48 | namespace boost { |
49 | namespace multiprecision { | |
50 | namespace backends { | |
7c673cae FG |
51 | |
52 | #ifdef BOOST_MSVC | |
53 | // warning C4127: conditional expression is constant | |
54 | #pragma warning(push) | |
92f5a8d4 | 55 | #pragma warning(disable : 4127) |
7c673cae FG |
56 | #endif |
57 | ||
58 | template <unsigned digits10> | |
59 | struct gmp_float; | |
60 | struct gmp_int; | |
61 | struct gmp_rational; | |
62 | ||
63 | } // namespace backends | |
64 | ||
92f5a8d4 TL |
65 | template <> |
66 | struct number_category<backends::gmp_int> : public mpl::int_<number_kind_integer> | |
67 | {}; | |
68 | template <> | |
69 | struct number_category<backends::gmp_rational> : public mpl::int_<number_kind_rational> | |
70 | {}; | |
7c673cae | 71 | template <unsigned digits10> |
92f5a8d4 TL |
72 | struct number_category<backends::gmp_float<digits10> > : public mpl::int_<number_kind_floating_point> |
73 | {}; | |
7c673cae | 74 | |
92f5a8d4 | 75 | namespace backends { |
7c673cae FG |
76 | // |
77 | // Within this file, the only functions we mark as noexcept are those that manipulate | |
78 | // (but don't create) an mpf_t. All other types may allocate at pretty much any time | |
79 | // via a user-supplied allocator, and therefore throw. | |
80 | // | |
92f5a8d4 | 81 | namespace detail { |
7c673cae FG |
82 | |
83 | template <unsigned digits10> | |
84 | struct gmp_float_imp | |
85 | { | |
86 | #ifdef BOOST_HAS_LONG_LONG | |
92f5a8d4 TL |
87 | typedef mpl::list<long, boost::long_long_type> signed_types; |
88 | typedef mpl::list<unsigned long, boost::ulong_long_type> unsigned_types; | |
7c673cae | 89 | #else |
92f5a8d4 TL |
90 | typedef mpl::list<long> signed_types; |
91 | typedef mpl::list<unsigned long> unsigned_types; | |
7c673cae | 92 | #endif |
92f5a8d4 TL |
93 | typedef mpl::list<double, long double> float_types; |
94 | typedef long exponent_type; | |
7c673cae | 95 | |
92f5a8d4 TL |
96 | gmp_float_imp() BOOST_NOEXCEPT |
97 | { | |
98 | m_data[0]._mp_d = 0; // uninitialized m_data | |
99 | } | |
7c673cae FG |
100 | |
101 | gmp_float_imp(const gmp_float_imp& o) | |
102 | { | |
103 | // | |
104 | // We have to do an init followed by a set here, otherwise *this may be at | |
105 | // a lower precision than o: seems like mpf_init_set copies just enough bits | |
106 | // to get the right value, but if it's then used in further calculations | |
107 | // things go badly wrong!! | |
108 | // | |
92f5a8d4 TL |
109 | mpf_init2(m_data, mpf_get_prec(o.data())); |
110 | if (o.m_data[0]._mp_d) | |
7c673cae FG |
111 | mpf_set(m_data, o.m_data); |
112 | } | |
113 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
114 | gmp_float_imp(gmp_float_imp&& o) BOOST_NOEXCEPT | |
115 | { | |
92f5a8d4 | 116 | m_data[0] = o.m_data[0]; |
7c673cae FG |
117 | o.m_data[0]._mp_d = 0; |
118 | } | |
119 | #endif | |
92f5a8d4 | 120 | gmp_float_imp& operator=(const gmp_float_imp& o) |
7c673cae | 121 | { |
92f5a8d4 TL |
122 | if (m_data[0]._mp_d == 0) |
123 | mpf_init2(m_data, mpf_get_prec(o.data())); | |
124 | if (mpf_get_prec(data()) != mpf_get_prec(o.data())) | |
125 | { | |
126 | mpf_t t; | |
127 | mpf_init2(t, mpf_get_prec(o.data())); | |
128 | mpf_set(t, o.data()); | |
129 | mpf_swap(data(), t); | |
130 | mpf_clear(t); | |
131 | } | |
132 | else | |
133 | { | |
134 | if (o.m_data[0]._mp_d) | |
135 | mpf_set(m_data, o.m_data); | |
136 | } | |
7c673cae FG |
137 | return *this; |
138 | } | |
139 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
92f5a8d4 | 140 | gmp_float_imp& operator=(gmp_float_imp&& o) BOOST_NOEXCEPT |
7c673cae FG |
141 | { |
142 | mpf_swap(m_data, o.m_data); | |
143 | return *this; | |
144 | } | |
145 | #endif | |
146 | ||
147 | #ifdef BOOST_HAS_LONG_LONG | |
148 | #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) | |
92f5a8d4 | 149 | gmp_float_imp& operator=(boost::ulong_long_type i) |
7c673cae FG |
150 | { |
151 | *this = static_cast<unsigned long>(i); | |
152 | return *this; | |
153 | } | |
154 | #else | |
92f5a8d4 | 155 | gmp_float_imp& operator=(boost::ulong_long_type i) |
7c673cae | 156 | { |
92f5a8d4 | 157 | if (m_data[0]._mp_d == 0) |
f67539c2 | 158 | mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
92f5a8d4 TL |
159 | boost::ulong_long_type mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL); |
160 | unsigned shift = 0; | |
161 | mpf_t t; | |
f67539c2 | 162 | mpf_init2(t, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
7c673cae | 163 | mpf_set_ui(m_data, 0); |
92f5a8d4 | 164 | while (i) |
7c673cae FG |
165 | { |
166 | mpf_set_ui(t, static_cast<unsigned long>(i & mask)); | |
92f5a8d4 | 167 | if (shift) |
7c673cae FG |
168 | mpf_mul_2exp(t, t, shift); |
169 | mpf_add(m_data, m_data, t); | |
170 | shift += std::numeric_limits<unsigned long>::digits; | |
171 | i >>= std::numeric_limits<unsigned long>::digits; | |
172 | } | |
173 | mpf_clear(t); | |
174 | return *this; | |
175 | } | |
176 | #endif | |
92f5a8d4 | 177 | gmp_float_imp& operator=(boost::long_long_type i) |
7c673cae | 178 | { |
92f5a8d4 | 179 | if (m_data[0]._mp_d == 0) |
f67539c2 | 180 | mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
7c673cae | 181 | bool neg = i < 0; |
92f5a8d4 TL |
182 | *this = static_cast<boost::ulong_long_type>(boost::multiprecision::detail::unsigned_abs(i)); |
183 | if (neg) | |
7c673cae FG |
184 | mpf_neg(m_data, m_data); |
185 | return *this; | |
186 | } | |
187 | #endif | |
92f5a8d4 | 188 | gmp_float_imp& operator=(unsigned long i) |
7c673cae | 189 | { |
92f5a8d4 | 190 | if (m_data[0]._mp_d == 0) |
f67539c2 | 191 | mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
7c673cae FG |
192 | mpf_set_ui(m_data, i); |
193 | return *this; | |
194 | } | |
92f5a8d4 | 195 | gmp_float_imp& operator=(long i) |
7c673cae | 196 | { |
92f5a8d4 | 197 | if (m_data[0]._mp_d == 0) |
f67539c2 | 198 | mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
7c673cae FG |
199 | mpf_set_si(m_data, i); |
200 | return *this; | |
201 | } | |
92f5a8d4 | 202 | gmp_float_imp& operator=(double d) |
7c673cae | 203 | { |
92f5a8d4 | 204 | if (m_data[0]._mp_d == 0) |
f67539c2 | 205 | mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
7c673cae FG |
206 | mpf_set_d(m_data, d); |
207 | return *this; | |
208 | } | |
92f5a8d4 | 209 | gmp_float_imp& operator=(long double a) |
7c673cae | 210 | { |
92f5a8d4 | 211 | using std::floor; |
7c673cae FG |
212 | using std::frexp; |
213 | using std::ldexp; | |
7c673cae | 214 | |
92f5a8d4 | 215 | if (m_data[0]._mp_d == 0) |
f67539c2 | 216 | mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
7c673cae | 217 | |
92f5a8d4 TL |
218 | if (a == 0) |
219 | { | |
7c673cae FG |
220 | mpf_set_si(m_data, 0); |
221 | return *this; | |
222 | } | |
223 | ||
92f5a8d4 TL |
224 | if (a == 1) |
225 | { | |
7c673cae FG |
226 | mpf_set_si(m_data, 1); |
227 | return *this; | |
228 | } | |
229 | ||
230 | BOOST_ASSERT(!(boost::math::isinf)(a)); | |
231 | BOOST_ASSERT(!(boost::math::isnan)(a)); | |
232 | ||
92f5a8d4 | 233 | int e; |
7c673cae FG |
234 | long double f, term; |
235 | mpf_set_ui(m_data, 0u); | |
236 | ||
237 | f = frexp(a, &e); | |
238 | ||
239 | static const int shift = std::numeric_limits<int>::digits - 1; | |
240 | ||
92f5a8d4 | 241 | while (f) |
7c673cae FG |
242 | { |
243 | // extract int sized bits from f: | |
92f5a8d4 | 244 | f = ldexp(f, shift); |
7c673cae FG |
245 | term = floor(f); |
246 | e -= shift; | |
247 | mpf_mul_2exp(m_data, m_data, shift); | |
92f5a8d4 | 248 | if (term > 0) |
7c673cae FG |
249 | mpf_add_ui(m_data, m_data, static_cast<unsigned>(term)); |
250 | else | |
251 | mpf_sub_ui(m_data, m_data, static_cast<unsigned>(-term)); | |
252 | f -= term; | |
253 | } | |
92f5a8d4 | 254 | if (e > 0) |
7c673cae | 255 | mpf_mul_2exp(m_data, m_data, e); |
92f5a8d4 | 256 | else if (e < 0) |
7c673cae FG |
257 | mpf_div_2exp(m_data, m_data, -e); |
258 | return *this; | |
259 | } | |
92f5a8d4 | 260 | gmp_float_imp& operator=(const char* s) |
7c673cae | 261 | { |
92f5a8d4 | 262 | if (m_data[0]._mp_d == 0) |
f67539c2 TL |
263 | mpf_init2(m_data, multiprecision::detail::digits10_2_2(digits10 ? digits10 : (unsigned)get_default_precision())); |
264 | if (s && (*s == '+')) | |
265 | ++s; // Leading "+" sign not supported by mpf_set_str: | |
92f5a8d4 | 266 | if (0 != mpf_set_str(m_data, s, 10)) |
7c673cae FG |
267 | BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid floating point number."))); |
268 | return *this; | |
269 | } | |
270 | void swap(gmp_float_imp& o) BOOST_NOEXCEPT | |
271 | { | |
272 | mpf_swap(m_data, o.m_data); | |
273 | } | |
92f5a8d4 | 274 | std::string str(std::streamsize digits, std::ios_base::fmtflags f) const |
7c673cae FG |
275 | { |
276 | BOOST_ASSERT(m_data[0]._mp_d); | |
277 | ||
92f5a8d4 TL |
278 | bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific; |
279 | bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed; | |
7c673cae FG |
280 | std::streamsize org_digits(digits); |
281 | ||
92f5a8d4 | 282 | if (scientific && digits) |
7c673cae FG |
283 | ++digits; |
284 | ||
285 | std::string result; | |
92f5a8d4 TL |
286 | mp_exp_t e; |
287 | void* (*alloc_func_ptr)(size_t); | |
288 | void* (*realloc_func_ptr)(void*, size_t, size_t); | |
289 | void (*free_func_ptr)(void*, size_t); | |
7c673cae FG |
290 | mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); |
291 | ||
92f5a8d4 | 292 | if (mpf_sgn(m_data) == 0) |
7c673cae | 293 | { |
92f5a8d4 | 294 | e = 0; |
7c673cae | 295 | result = "0"; |
92f5a8d4 | 296 | if (fixed && digits) |
7c673cae FG |
297 | ++digits; |
298 | } | |
299 | else | |
300 | { | |
92f5a8d4 TL |
301 | char* ps = mpf_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data); |
302 | --e; // To match with what our formatter expects. | |
303 | if (fixed && e != -1) | |
7c673cae FG |
304 | { |
305 | // Oops we actually need a different number of digits to what we asked for: | |
306 | (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); | |
307 | digits += e + 1; | |
92f5a8d4 | 308 | if (digits == 0) |
7c673cae FG |
309 | { |
310 | // We need to get *all* the digits and then possibly round up, | |
311 | // we end up with either "0" or "1" as the result. | |
92f5a8d4 | 312 | ps = mpf_get_str(0, &e, 10, 0, m_data); |
7c673cae FG |
313 | --e; |
314 | unsigned offset = *ps == '-' ? 1 : 0; | |
92f5a8d4 | 315 | if (ps[offset] > '5') |
7c673cae FG |
316 | { |
317 | ++e; | |
92f5a8d4 | 318 | ps[offset] = '1'; |
7c673cae FG |
319 | ps[offset + 1] = 0; |
320 | } | |
92f5a8d4 | 321 | else if (ps[offset] == '5') |
7c673cae | 322 | { |
92f5a8d4 TL |
323 | unsigned i = offset + 1; |
324 | bool round_up = false; | |
325 | while (ps[i] != 0) | |
7c673cae | 326 | { |
92f5a8d4 | 327 | if (ps[i] != '0') |
7c673cae FG |
328 | { |
329 | round_up = true; | |
330 | break; | |
331 | } | |
92f5a8d4 | 332 | ++i; |
7c673cae | 333 | } |
92f5a8d4 | 334 | if (round_up) |
7c673cae FG |
335 | { |
336 | ++e; | |
92f5a8d4 | 337 | ps[offset] = '1'; |
7c673cae FG |
338 | ps[offset + 1] = 0; |
339 | } | |
340 | else | |
341 | { | |
92f5a8d4 | 342 | ps[offset] = '0'; |
7c673cae FG |
343 | ps[offset + 1] = 0; |
344 | } | |
345 | } | |
346 | else | |
347 | { | |
92f5a8d4 | 348 | ps[offset] = '0'; |
7c673cae FG |
349 | ps[offset + 1] = 0; |
350 | } | |
351 | } | |
92f5a8d4 | 352 | else if (digits > 0) |
7c673cae | 353 | { |
92f5a8d4 TL |
354 | mp_exp_t old_e = e; |
355 | ps = mpf_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data); | |
356 | --e; // To match with what our formatter expects. | |
357 | if (old_e > e) | |
358 | { | |
359 | // in some cases, when we ask for more digits of precision, it will | |
360 | // change the number of digits to the left of the decimal, if that | |
361 | // happens, account for it here. | |
362 | // example: cout << fixed << setprecision(3) << mpf_float_50("99.9809") | |
363 | digits -= old_e - e; | |
364 | ps = mpf_get_str(0, &e, 10, static_cast<std::size_t>(digits), m_data); | |
365 | --e; // To match with what our formatter expects. | |
366 | } | |
7c673cae FG |
367 | } |
368 | else | |
369 | { | |
92f5a8d4 | 370 | ps = mpf_get_str(0, &e, 10, 1, m_data); |
7c673cae FG |
371 | --e; |
372 | unsigned offset = *ps == '-' ? 1 : 0; | |
92f5a8d4 TL |
373 | ps[offset] = '0'; |
374 | ps[offset + 1] = 0; | |
7c673cae FG |
375 | } |
376 | } | |
377 | result = ps; | |
378 | (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); | |
379 | } | |
380 | boost::multiprecision::detail::format_float_string(result, e, org_digits, f, mpf_sgn(m_data) == 0); | |
381 | return result; | |
382 | } | |
383 | ~gmp_float_imp() BOOST_NOEXCEPT | |
384 | { | |
92f5a8d4 | 385 | if (m_data[0]._mp_d) |
7c673cae FG |
386 | mpf_clear(m_data); |
387 | } | |
388 | void negate() BOOST_NOEXCEPT | |
389 | { | |
390 | BOOST_ASSERT(m_data[0]._mp_d); | |
391 | mpf_neg(m_data, m_data); | |
392 | } | |
92f5a8d4 | 393 | int compare(const gmp_float<digits10>& o) const BOOST_NOEXCEPT |
7c673cae FG |
394 | { |
395 | BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d); | |
396 | return mpf_cmp(m_data, o.m_data); | |
397 | } | |
92f5a8d4 | 398 | int compare(long i) const BOOST_NOEXCEPT |
7c673cae FG |
399 | { |
400 | BOOST_ASSERT(m_data[0]._mp_d); | |
401 | return mpf_cmp_si(m_data, i); | |
402 | } | |
92f5a8d4 | 403 | int compare(unsigned long i) const BOOST_NOEXCEPT |
7c673cae FG |
404 | { |
405 | BOOST_ASSERT(m_data[0]._mp_d); | |
406 | return mpf_cmp_ui(m_data, i); | |
407 | } | |
408 | template <class V> | |
92f5a8d4 | 409 | typename enable_if<is_arithmetic<V>, int>::type compare(V v) const |
7c673cae FG |
410 | { |
411 | gmp_float<digits10> d; | |
412 | d = v; | |
413 | return compare(d); | |
414 | } | |
415 | mpf_t& data() BOOST_NOEXCEPT | |
416 | { | |
417 | BOOST_ASSERT(m_data[0]._mp_d); | |
418 | return m_data; | |
419 | } | |
92f5a8d4 | 420 | const mpf_t& data() const BOOST_NOEXCEPT |
7c673cae FG |
421 | { |
422 | BOOST_ASSERT(m_data[0]._mp_d); | |
423 | return m_data; | |
424 | } | |
92f5a8d4 TL |
425 | |
426 | protected: | |
427 | mpf_t m_data; | |
f67539c2 | 428 | static boost::multiprecision::detail::precision_type& get_default_precision() BOOST_NOEXCEPT |
7c673cae | 429 | { |
f67539c2 | 430 | static boost::multiprecision::detail::precision_type val(50); |
7c673cae FG |
431 | return val; |
432 | } | |
433 | }; | |
434 | ||
435 | } // namespace detail | |
436 | ||
437 | struct gmp_int; | |
438 | struct gmp_rational; | |
439 | ||
440 | template <unsigned digits10> | |
441 | struct gmp_float : public detail::gmp_float_imp<digits10> | |
442 | { | |
443 | gmp_float() | |
444 | { | |
445 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); | |
446 | } | |
447 | gmp_float(const gmp_float& o) : detail::gmp_float_imp<digits10>(o) {} | |
448 | template <unsigned D> | |
449 | gmp_float(const gmp_float<D>& o, typename enable_if_c<D <= digits10>::type* = 0); | |
450 | template <unsigned D> | |
451 | explicit gmp_float(const gmp_float<D>& o, typename disable_if_c<D <= digits10>::type* = 0); | |
452 | gmp_float(const gmp_int& o); | |
453 | gmp_float(const gmp_rational& o); | |
454 | gmp_float(const mpf_t val) | |
455 | { | |
456 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); | |
457 | mpf_set(this->m_data, val); | |
458 | } | |
459 | gmp_float(const mpz_t val) | |
460 | { | |
461 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); | |
462 | mpf_set_z(this->m_data, val); | |
463 | } | |
464 | gmp_float(const mpq_t val) | |
465 | { | |
466 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); | |
467 | mpf_set_q(this->m_data, val); | |
468 | } | |
469 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
92f5a8d4 TL |
470 | gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp<digits10>(static_cast<detail::gmp_float_imp<digits10>&&>(o)) |
471 | {} | |
7c673cae FG |
472 | #endif |
473 | gmp_float& operator=(const gmp_float& o) | |
474 | { | |
475 | *static_cast<detail::gmp_float_imp<digits10>*>(this) = static_cast<detail::gmp_float_imp<digits10> const&>(o); | |
476 | return *this; | |
477 | } | |
478 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
479 | gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT | |
480 | { | |
481 | *static_cast<detail::gmp_float_imp<digits10>*>(this) = static_cast<detail::gmp_float_imp<digits10>&&>(o); | |
482 | return *this; | |
483 | } | |
484 | #endif | |
485 | template <unsigned D> | |
486 | gmp_float& operator=(const gmp_float<D>& o); | |
487 | gmp_float& operator=(const gmp_int& o); | |
488 | gmp_float& operator=(const gmp_rational& o); | |
489 | gmp_float& operator=(const mpf_t val) | |
490 | { | |
92f5a8d4 | 491 | if (this->m_data[0]._mp_d == 0) |
7c673cae FG |
492 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); |
493 | mpf_set(this->m_data, val); | |
494 | return *this; | |
495 | } | |
496 | gmp_float& operator=(const mpz_t val) | |
497 | { | |
92f5a8d4 | 498 | if (this->m_data[0]._mp_d == 0) |
7c673cae FG |
499 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); |
500 | mpf_set_z(this->m_data, val); | |
501 | return *this; | |
502 | } | |
503 | gmp_float& operator=(const mpq_t val) | |
504 | { | |
92f5a8d4 | 505 | if (this->m_data[0]._mp_d == 0) |
7c673cae FG |
506 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); |
507 | mpf_set_q(this->m_data, val); | |
508 | return *this; | |
509 | } | |
510 | template <class V> | |
511 | gmp_float& operator=(const V& v) | |
512 | { | |
513 | *static_cast<detail::gmp_float_imp<digits10>*>(this) = v; | |
514 | return *this; | |
515 | } | |
516 | }; | |
517 | ||
518 | template <> | |
519 | struct gmp_float<0> : public detail::gmp_float_imp<0> | |
520 | { | |
f67539c2 TL |
521 | // |
522 | // We have a problem with mpf_t in that the precision we request isn't what we get. | |
523 | // As a result the front end can end up chasing it's tail trying to create a variable | |
524 | // with the the correct precision to hold the result of an expression. | |
525 | // See: https://github.com/boostorg/multiprecision/issues/164 | |
526 | // The problem is made worse by the fact that our conversions from base10 to 2 and | |
527 | // vice-versa do not exactly round trip (and probably never will). | |
528 | // The workaround is to keep track of the precision requested, and always return | |
529 | // that as the current actual precision. | |
530 | // | |
531 | private: | |
532 | unsigned requested_precision; | |
533 | ||
534 | public: | |
535 | gmp_float() : requested_precision(get_default_precision()) | |
7c673cae | 536 | { |
f67539c2 | 537 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); |
7c673cae | 538 | } |
f67539c2 | 539 | gmp_float(const mpf_t val) : requested_precision(get_default_precision()) |
7c673cae | 540 | { |
f67539c2 | 541 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); |
7c673cae FG |
542 | mpf_set(this->m_data, val); |
543 | } | |
f67539c2 | 544 | gmp_float(const mpz_t val) : requested_precision(get_default_precision()) |
7c673cae | 545 | { |
f67539c2 | 546 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); |
7c673cae FG |
547 | mpf_set_z(this->m_data, val); |
548 | } | |
f67539c2 | 549 | gmp_float(const mpq_t val) : requested_precision(get_default_precision()) |
7c673cae | 550 | { |
f67539c2 | 551 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); |
7c673cae FG |
552 | mpf_set_q(this->m_data, val); |
553 | } | |
f67539c2 | 554 | gmp_float(const gmp_float& o) : detail::gmp_float_imp<0>(o), requested_precision(o.requested_precision) {} |
7c673cae FG |
555 | template <unsigned D> |
556 | gmp_float(const gmp_float<D>& o) | |
557 | { | |
558 | mpf_init2(this->m_data, mpf_get_prec(o.data())); | |
559 | mpf_set(this->m_data, o.data()); | |
f67539c2 | 560 | requested_precision = D; |
7c673cae FG |
561 | } |
562 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
f67539c2 | 563 | gmp_float(gmp_float&& o) BOOST_NOEXCEPT : detail::gmp_float_imp<0>(static_cast<detail::gmp_float_imp<0>&&>(o)), requested_precision(o.requested_precision) |
92f5a8d4 | 564 | {} |
7c673cae FG |
565 | #endif |
566 | gmp_float(const gmp_int& o); | |
567 | gmp_float(const gmp_rational& o); | |
f67539c2 | 568 | gmp_float(const gmp_float& o, unsigned digits10) : requested_precision(digits10) |
7c673cae FG |
569 | { |
570 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); | |
571 | mpf_set(this->m_data, o.data()); | |
572 | } | |
92f5a8d4 | 573 | template <class V> |
f67539c2 | 574 | gmp_float(const V& o, unsigned digits10) : requested_precision(digits10) |
92f5a8d4 TL |
575 | { |
576 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); | |
577 | *this = o; | |
578 | } | |
7c673cae | 579 | |
92f5a8d4 TL |
580 | #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW |
581 | // | |
582 | // Support for new types in C++17 | |
583 | // | |
584 | template <class Traits> | |
f67539c2 | 585 | gmp_float(const std::basic_string_view<char, Traits>& o, unsigned digits10) : requested_precision(digits10) |
92f5a8d4 TL |
586 | { |
587 | using default_ops::assign_from_string_view; | |
588 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(digits10)); | |
589 | assign_from_string_view(*this, o); | |
590 | } | |
591 | #endif | |
7c673cae FG |
592 | gmp_float& operator=(const gmp_float& o) |
593 | { | |
594 | *static_cast<detail::gmp_float_imp<0>*>(this) = static_cast<detail::gmp_float_imp<0> const&>(o); | |
f67539c2 | 595 | requested_precision = o.requested_precision; |
7c673cae FG |
596 | return *this; |
597 | } | |
598 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
599 | gmp_float& operator=(gmp_float&& o) BOOST_NOEXCEPT | |
600 | { | |
92f5a8d4 | 601 | *static_cast<detail::gmp_float_imp<0>*>(this) = static_cast<detail::gmp_float_imp<0>&&>(o); |
f67539c2 | 602 | requested_precision = o.requested_precision; |
7c673cae FG |
603 | return *this; |
604 | } | |
605 | #endif | |
606 | template <unsigned D> | |
607 | gmp_float& operator=(const gmp_float<D>& o) | |
608 | { | |
92f5a8d4 | 609 | if (this->m_data[0]._mp_d == 0) |
7c673cae FG |
610 | { |
611 | mpf_init2(this->m_data, mpf_get_prec(o.data())); | |
612 | } | |
613 | else | |
614 | { | |
615 | mpf_set_prec(this->m_data, mpf_get_prec(o.data())); | |
616 | } | |
617 | mpf_set(this->m_data, o.data()); | |
f67539c2 | 618 | requested_precision = D; |
7c673cae FG |
619 | return *this; |
620 | } | |
621 | gmp_float& operator=(const gmp_int& o); | |
622 | gmp_float& operator=(const gmp_rational& o); | |
623 | gmp_float& operator=(const mpf_t val) | |
624 | { | |
92f5a8d4 | 625 | if (this->m_data[0]._mp_d == 0) |
f67539c2 TL |
626 | { |
627 | requested_precision = get_default_precision(); | |
628 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); | |
629 | } | |
7c673cae FG |
630 | mpf_set(this->m_data, val); |
631 | return *this; | |
632 | } | |
633 | gmp_float& operator=(const mpz_t val) | |
634 | { | |
92f5a8d4 | 635 | if (this->m_data[0]._mp_d == 0) |
f67539c2 TL |
636 | { |
637 | requested_precision = get_default_precision(); | |
638 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); | |
639 | } | |
7c673cae FG |
640 | mpf_set_z(this->m_data, val); |
641 | return *this; | |
642 | } | |
643 | gmp_float& operator=(const mpq_t val) | |
644 | { | |
92f5a8d4 | 645 | if (this->m_data[0]._mp_d == 0) |
f67539c2 TL |
646 | { |
647 | requested_precision = get_default_precision(); | |
648 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); | |
649 | } | |
7c673cae FG |
650 | mpf_set_q(this->m_data, val); |
651 | return *this; | |
652 | } | |
653 | template <class V> | |
654 | gmp_float& operator=(const V& v) | |
655 | { | |
656 | *static_cast<detail::gmp_float_imp<0>*>(this) = v; | |
657 | return *this; | |
658 | } | |
659 | static unsigned default_precision() BOOST_NOEXCEPT | |
660 | { | |
661 | return get_default_precision(); | |
662 | } | |
663 | static void default_precision(unsigned v) BOOST_NOEXCEPT | |
664 | { | |
665 | get_default_precision() = v; | |
666 | } | |
92f5a8d4 | 667 | unsigned precision() const BOOST_NOEXCEPT |
7c673cae | 668 | { |
f67539c2 | 669 | return requested_precision; |
7c673cae FG |
670 | } |
671 | void precision(unsigned digits10) BOOST_NOEXCEPT | |
672 | { | |
f67539c2 TL |
673 | requested_precision = digits10; |
674 | mpf_set_prec(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); | |
675 | } | |
676 | void swap(gmp_float& o) | |
677 | { | |
678 | std::swap(requested_precision, o.requested_precision); | |
679 | gmp_float_imp<0>::swap(o); | |
7c673cae FG |
680 | } |
681 | }; | |
682 | ||
683 | template <unsigned digits10, class T> | |
684 | inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_eq(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT | |
685 | { | |
686 | return a.compare(b) == 0; | |
687 | } | |
688 | template <unsigned digits10, class T> | |
689 | inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_lt(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT | |
690 | { | |
691 | return a.compare(b) < 0; | |
692 | } | |
693 | template <unsigned digits10, class T> | |
694 | inline typename enable_if_c<is_arithmetic<T>::value, bool>::type eval_gt(const gmp_float<digits10>& a, const T& b) BOOST_NOEXCEPT | |
695 | { | |
696 | return a.compare(b) > 0; | |
697 | } | |
698 | ||
699 | template <unsigned D1, unsigned D2> | |
700 | inline void eval_add(gmp_float<D1>& result, const gmp_float<D2>& o) | |
701 | { | |
702 | mpf_add(result.data(), result.data(), o.data()); | |
703 | } | |
704 | template <unsigned D1, unsigned D2> | |
705 | inline void eval_subtract(gmp_float<D1>& result, const gmp_float<D2>& o) | |
706 | { | |
707 | mpf_sub(result.data(), result.data(), o.data()); | |
708 | } | |
709 | template <unsigned D1, unsigned D2> | |
710 | inline void eval_multiply(gmp_float<D1>& result, const gmp_float<D2>& o) | |
711 | { | |
712 | mpf_mul(result.data(), result.data(), o.data()); | |
713 | } | |
714 | template <unsigned digits10> | |
715 | inline bool eval_is_zero(const gmp_float<digits10>& val) BOOST_NOEXCEPT | |
716 | { | |
717 | return mpf_sgn(val.data()) == 0; | |
718 | } | |
719 | template <unsigned D1, unsigned D2> | |
720 | inline void eval_divide(gmp_float<D1>& result, const gmp_float<D2>& o) | |
721 | { | |
92f5a8d4 | 722 | if (eval_is_zero(o)) |
7c673cae FG |
723 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
724 | mpf_div(result.data(), result.data(), o.data()); | |
725 | } | |
726 | template <unsigned digits10> | |
727 | inline void eval_add(gmp_float<digits10>& result, unsigned long i) | |
728 | { | |
729 | mpf_add_ui(result.data(), result.data(), i); | |
730 | } | |
731 | template <unsigned digits10> | |
732 | inline void eval_subtract(gmp_float<digits10>& result, unsigned long i) | |
733 | { | |
734 | mpf_sub_ui(result.data(), result.data(), i); | |
735 | } | |
736 | template <unsigned digits10> | |
737 | inline void eval_multiply(gmp_float<digits10>& result, unsigned long i) | |
738 | { | |
739 | mpf_mul_ui(result.data(), result.data(), i); | |
740 | } | |
741 | template <unsigned digits10> | |
742 | inline void eval_divide(gmp_float<digits10>& result, unsigned long i) | |
743 | { | |
92f5a8d4 | 744 | if (i == 0) |
7c673cae FG |
745 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
746 | mpf_div_ui(result.data(), result.data(), i); | |
747 | } | |
748 | template <unsigned digits10> | |
749 | inline void eval_add(gmp_float<digits10>& result, long i) | |
750 | { | |
92f5a8d4 | 751 | if (i > 0) |
7c673cae FG |
752 | mpf_add_ui(result.data(), result.data(), i); |
753 | else | |
754 | mpf_sub_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
755 | } | |
756 | template <unsigned digits10> | |
757 | inline void eval_subtract(gmp_float<digits10>& result, long i) | |
758 | { | |
92f5a8d4 | 759 | if (i > 0) |
7c673cae FG |
760 | mpf_sub_ui(result.data(), result.data(), i); |
761 | else | |
762 | mpf_add_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
763 | } | |
764 | template <unsigned digits10> | |
765 | inline void eval_multiply(gmp_float<digits10>& result, long i) | |
766 | { | |
767 | mpf_mul_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
92f5a8d4 | 768 | if (i < 0) |
7c673cae FG |
769 | mpf_neg(result.data(), result.data()); |
770 | } | |
771 | template <unsigned digits10> | |
772 | inline void eval_divide(gmp_float<digits10>& result, long i) | |
773 | { | |
92f5a8d4 | 774 | if (i == 0) |
7c673cae FG |
775 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
776 | mpf_div_ui(result.data(), result.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
92f5a8d4 | 777 | if (i < 0) |
7c673cae FG |
778 | mpf_neg(result.data(), result.data()); |
779 | } | |
780 | // | |
781 | // Specialised 3 arg versions of the basic operators: | |
782 | // | |
783 | template <unsigned D1, unsigned D2, unsigned D3> | |
784 | inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y) | |
785 | { | |
786 | mpf_add(a.data(), x.data(), y.data()); | |
787 | } | |
788 | template <unsigned D1, unsigned D2> | |
789 | inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y) | |
790 | { | |
791 | mpf_add_ui(a.data(), x.data(), y); | |
792 | } | |
793 | template <unsigned D1, unsigned D2> | |
794 | inline void eval_add(gmp_float<D1>& a, const gmp_float<D2>& x, long y) | |
795 | { | |
92f5a8d4 | 796 | if (y < 0) |
7c673cae FG |
797 | mpf_sub_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); |
798 | else | |
799 | mpf_add_ui(a.data(), x.data(), y); | |
800 | } | |
801 | template <unsigned D1, unsigned D2> | |
802 | inline void eval_add(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y) | |
803 | { | |
804 | mpf_add_ui(a.data(), y.data(), x); | |
805 | } | |
806 | template <unsigned D1, unsigned D2> | |
807 | inline void eval_add(gmp_float<D1>& a, long x, const gmp_float<D2>& y) | |
808 | { | |
92f5a8d4 | 809 | if (x < 0) |
7c673cae FG |
810 | { |
811 | mpf_ui_sub(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data()); | |
812 | mpf_neg(a.data(), a.data()); | |
813 | } | |
814 | else | |
815 | mpf_add_ui(a.data(), y.data(), x); | |
816 | } | |
817 | template <unsigned D1, unsigned D2, unsigned D3> | |
818 | inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y) | |
819 | { | |
820 | mpf_sub(a.data(), x.data(), y.data()); | |
821 | } | |
822 | template <unsigned D1, unsigned D2> | |
823 | inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y) | |
824 | { | |
825 | mpf_sub_ui(a.data(), x.data(), y); | |
826 | } | |
827 | template <unsigned D1, unsigned D2> | |
828 | inline void eval_subtract(gmp_float<D1>& a, const gmp_float<D2>& x, long y) | |
829 | { | |
92f5a8d4 | 830 | if (y < 0) |
7c673cae FG |
831 | mpf_add_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); |
832 | else | |
833 | mpf_sub_ui(a.data(), x.data(), y); | |
834 | } | |
835 | template <unsigned D1, unsigned D2> | |
836 | inline void eval_subtract(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y) | |
837 | { | |
838 | mpf_ui_sub(a.data(), x, y.data()); | |
839 | } | |
840 | template <unsigned D1, unsigned D2> | |
841 | inline void eval_subtract(gmp_float<D1>& a, long x, const gmp_float<D2>& y) | |
842 | { | |
92f5a8d4 | 843 | if (x < 0) |
7c673cae FG |
844 | { |
845 | mpf_add_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x)); | |
846 | mpf_neg(a.data(), a.data()); | |
847 | } | |
848 | else | |
849 | mpf_ui_sub(a.data(), x, y.data()); | |
850 | } | |
851 | ||
852 | template <unsigned D1, unsigned D2, unsigned D3> | |
853 | inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y) | |
854 | { | |
855 | mpf_mul(a.data(), x.data(), y.data()); | |
856 | } | |
857 | template <unsigned D1, unsigned D2> | |
858 | inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y) | |
859 | { | |
860 | mpf_mul_ui(a.data(), x.data(), y); | |
861 | } | |
862 | template <unsigned D1, unsigned D2> | |
863 | inline void eval_multiply(gmp_float<D1>& a, const gmp_float<D2>& x, long y) | |
864 | { | |
92f5a8d4 | 865 | if (y < 0) |
7c673cae FG |
866 | { |
867 | mpf_mul_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); | |
868 | a.negate(); | |
869 | } | |
870 | else | |
871 | mpf_mul_ui(a.data(), x.data(), y); | |
872 | } | |
873 | template <unsigned D1, unsigned D2> | |
874 | inline void eval_multiply(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y) | |
875 | { | |
876 | mpf_mul_ui(a.data(), y.data(), x); | |
877 | } | |
878 | template <unsigned D1, unsigned D2> | |
879 | inline void eval_multiply(gmp_float<D1>& a, long x, const gmp_float<D2>& y) | |
880 | { | |
92f5a8d4 | 881 | if (x < 0) |
7c673cae FG |
882 | { |
883 | mpf_mul_ui(a.data(), y.data(), boost::multiprecision::detail::unsigned_abs(x)); | |
884 | mpf_neg(a.data(), a.data()); | |
885 | } | |
886 | else | |
887 | mpf_mul_ui(a.data(), y.data(), x); | |
888 | } | |
889 | ||
890 | template <unsigned D1, unsigned D2, unsigned D3> | |
891 | inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, const gmp_float<D3>& y) | |
892 | { | |
92f5a8d4 | 893 | if (eval_is_zero(y)) |
7c673cae FG |
894 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
895 | mpf_div(a.data(), x.data(), y.data()); | |
896 | } | |
897 | template <unsigned D1, unsigned D2> | |
898 | inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, unsigned long y) | |
899 | { | |
92f5a8d4 | 900 | if (y == 0) |
7c673cae FG |
901 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
902 | mpf_div_ui(a.data(), x.data(), y); | |
903 | } | |
904 | template <unsigned D1, unsigned D2> | |
905 | inline void eval_divide(gmp_float<D1>& a, const gmp_float<D2>& x, long y) | |
906 | { | |
92f5a8d4 | 907 | if (y == 0) |
7c673cae | 908 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
92f5a8d4 | 909 | if (y < 0) |
7c673cae FG |
910 | { |
911 | mpf_div_ui(a.data(), x.data(), boost::multiprecision::detail::unsigned_abs(y)); | |
912 | a.negate(); | |
913 | } | |
914 | else | |
915 | mpf_div_ui(a.data(), x.data(), y); | |
916 | } | |
917 | template <unsigned D1, unsigned D2> | |
918 | inline void eval_divide(gmp_float<D1>& a, unsigned long x, const gmp_float<D2>& y) | |
919 | { | |
92f5a8d4 | 920 | if (eval_is_zero(y)) |
7c673cae FG |
921 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
922 | mpf_ui_div(a.data(), x, y.data()); | |
923 | } | |
924 | template <unsigned D1, unsigned D2> | |
925 | inline void eval_divide(gmp_float<D1>& a, long x, const gmp_float<D2>& y) | |
926 | { | |
92f5a8d4 | 927 | if (eval_is_zero(y)) |
7c673cae | 928 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
92f5a8d4 | 929 | if (x < 0) |
7c673cae FG |
930 | { |
931 | mpf_ui_div(a.data(), boost::multiprecision::detail::unsigned_abs(x), y.data()); | |
932 | mpf_neg(a.data(), a.data()); | |
933 | } | |
934 | else | |
935 | mpf_ui_div(a.data(), x, y.data()); | |
936 | } | |
937 | ||
938 | template <unsigned digits10> | |
939 | inline int eval_get_sign(const gmp_float<digits10>& val) BOOST_NOEXCEPT | |
940 | { | |
941 | return mpf_sgn(val.data()); | |
942 | } | |
943 | ||
944 | template <unsigned digits10> | |
945 | inline void eval_convert_to(unsigned long* result, const gmp_float<digits10>& val) BOOST_NOEXCEPT | |
946 | { | |
92f5a8d4 | 947 | if (0 == mpf_fits_ulong_p(val.data())) |
7c673cae FG |
948 | *result = (std::numeric_limits<unsigned long>::max)(); |
949 | else | |
11fdf7f2 | 950 | *result = (unsigned long)mpf_get_ui(val.data()); |
7c673cae FG |
951 | } |
952 | template <unsigned digits10> | |
953 | inline void eval_convert_to(long* result, const gmp_float<digits10>& val) BOOST_NOEXCEPT | |
954 | { | |
92f5a8d4 | 955 | if (0 == mpf_fits_slong_p(val.data())) |
7c673cae | 956 | { |
b32b8144 | 957 | *result = (std::numeric_limits<long>::max)(); |
7c673cae FG |
958 | *result *= mpf_sgn(val.data()); |
959 | } | |
960 | else | |
11fdf7f2 | 961 | *result = (long)mpf_get_si(val.data()); |
7c673cae FG |
962 | } |
963 | template <unsigned digits10> | |
964 | inline void eval_convert_to(double* result, const gmp_float<digits10>& val) BOOST_NOEXCEPT | |
965 | { | |
966 | *result = mpf_get_d(val.data()); | |
967 | } | |
968 | #ifdef BOOST_HAS_LONG_LONG | |
969 | template <unsigned digits10> | |
970 | inline void eval_convert_to(boost::long_long_type* result, const gmp_float<digits10>& val) | |
971 | { | |
972 | gmp_float<digits10> t(val); | |
92f5a8d4 | 973 | if (eval_get_sign(t) < 0) |
7c673cae FG |
974 | t.negate(); |
975 | ||
976 | long digits = std::numeric_limits<boost::long_long_type>::digits - std::numeric_limits<long>::digits; | |
977 | ||
92f5a8d4 | 978 | if (digits > 0) |
7c673cae FG |
979 | mpf_div_2exp(t.data(), t.data(), digits); |
980 | ||
92f5a8d4 | 981 | if (!mpf_fits_slong_p(t.data())) |
7c673cae | 982 | { |
92f5a8d4 | 983 | if (eval_get_sign(val) < 0) |
7c673cae FG |
984 | *result = (std::numeric_limits<boost::long_long_type>::min)(); |
985 | else | |
986 | *result = (std::numeric_limits<boost::long_long_type>::max)(); | |
987 | return; | |
988 | }; | |
989 | ||
990 | *result = mpf_get_si(t.data()); | |
92f5a8d4 | 991 | while (digits > 0) |
7c673cae FG |
992 | { |
993 | *result <<= digits; | |
994 | digits -= std::numeric_limits<unsigned long>::digits; | |
995 | mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits<unsigned long>::digits : std::numeric_limits<unsigned long>::digits + digits); | |
11fdf7f2 | 996 | unsigned long l = (unsigned long)mpf_get_ui(t.data()); |
92f5a8d4 | 997 | if (digits < 0) |
7c673cae FG |
998 | l >>= -digits; |
999 | *result |= l; | |
1000 | } | |
92f5a8d4 | 1001 | if (eval_get_sign(val) < 0) |
7c673cae FG |
1002 | *result = -*result; |
1003 | } | |
1004 | template <unsigned digits10> | |
1005 | inline void eval_convert_to(boost::ulong_long_type* result, const gmp_float<digits10>& val) | |
1006 | { | |
1007 | gmp_float<digits10> t(val); | |
1008 | ||
1009 | long digits = std::numeric_limits<boost::long_long_type>::digits - std::numeric_limits<long>::digits; | |
1010 | ||
92f5a8d4 | 1011 | if (digits > 0) |
7c673cae FG |
1012 | mpf_div_2exp(t.data(), t.data(), digits); |
1013 | ||
92f5a8d4 | 1014 | if (!mpf_fits_ulong_p(t.data())) |
7c673cae FG |
1015 | { |
1016 | *result = (std::numeric_limits<boost::long_long_type>::max)(); | |
1017 | return; | |
1018 | } | |
1019 | ||
1020 | *result = mpf_get_ui(t.data()); | |
92f5a8d4 | 1021 | while (digits > 0) |
7c673cae FG |
1022 | { |
1023 | *result <<= digits; | |
1024 | digits -= std::numeric_limits<unsigned long>::digits; | |
1025 | mpf_mul_2exp(t.data(), t.data(), digits >= 0 ? std::numeric_limits<unsigned long>::digits : std::numeric_limits<unsigned long>::digits + digits); | |
11fdf7f2 | 1026 | unsigned long l = (unsigned long)mpf_get_ui(t.data()); |
92f5a8d4 | 1027 | if (digits < 0) |
7c673cae FG |
1028 | l >>= -digits; |
1029 | *result |= l; | |
1030 | } | |
1031 | } | |
1032 | #endif | |
1033 | ||
1034 | // | |
1035 | // Native non-member operations: | |
1036 | // | |
1037 | template <unsigned Digits10> | |
1038 | inline void eval_sqrt(gmp_float<Digits10>& result, const gmp_float<Digits10>& val) | |
1039 | { | |
1040 | mpf_sqrt(result.data(), val.data()); | |
1041 | } | |
1042 | ||
1043 | template <unsigned Digits10> | |
1044 | inline void eval_abs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val) | |
1045 | { | |
1046 | mpf_abs(result.data(), val.data()); | |
1047 | } | |
1048 | ||
1049 | template <unsigned Digits10> | |
1050 | inline void eval_fabs(gmp_float<Digits10>& result, const gmp_float<Digits10>& val) | |
1051 | { | |
1052 | mpf_abs(result.data(), val.data()); | |
1053 | } | |
1054 | template <unsigned Digits10> | |
1055 | inline void eval_ceil(gmp_float<Digits10>& result, const gmp_float<Digits10>& val) | |
1056 | { | |
1057 | mpf_ceil(result.data(), val.data()); | |
1058 | } | |
1059 | template <unsigned Digits10> | |
1060 | inline void eval_floor(gmp_float<Digits10>& result, const gmp_float<Digits10>& val) | |
1061 | { | |
1062 | mpf_floor(result.data(), val.data()); | |
1063 | } | |
1064 | template <unsigned Digits10> | |
1065 | inline void eval_trunc(gmp_float<Digits10>& result, const gmp_float<Digits10>& val) | |
1066 | { | |
1067 | mpf_trunc(result.data(), val.data()); | |
1068 | } | |
1069 | template <unsigned Digits10> | |
1070 | inline void eval_ldexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long e) | |
1071 | { | |
92f5a8d4 | 1072 | if (e > 0) |
7c673cae | 1073 | mpf_mul_2exp(result.data(), val.data(), e); |
92f5a8d4 | 1074 | else if (e < 0) |
7c673cae FG |
1075 | mpf_div_2exp(result.data(), val.data(), -e); |
1076 | else | |
1077 | result = val; | |
1078 | } | |
1079 | template <unsigned Digits10> | |
1080 | inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, int* e) | |
1081 | { | |
11fdf7f2 | 1082 | #if (BOOST_MP_MPIR_VERSION >= 20600) && (BOOST_MP_MPIR_VERSION < 30000) |
7c673cae FG |
1083 | mpir_si v; |
1084 | mpf_get_d_2exp(&v, val.data()); | |
1085 | #else | |
92f5a8d4 | 1086 | long v; |
7c673cae FG |
1087 | mpf_get_d_2exp(&v, val.data()); |
1088 | #endif | |
1089 | *e = v; | |
1090 | eval_ldexp(result, val, -v); | |
1091 | } | |
1092 | template <unsigned Digits10> | |
1093 | inline void eval_frexp(gmp_float<Digits10>& result, const gmp_float<Digits10>& val, long* e) | |
1094 | { | |
11fdf7f2 | 1095 | #if (BOOST_MP_MPIR_VERSION >= 20600) && (BOOST_MP_MPIR_VERSION < 30000) |
7c673cae FG |
1096 | mpir_si v; |
1097 | mpf_get_d_2exp(&v, val.data()); | |
1098 | *e = v; | |
1099 | eval_ldexp(result, val, -v); | |
1100 | #else | |
1101 | mpf_get_d_2exp(e, val.data()); | |
1102 | eval_ldexp(result, val, -*e); | |
1103 | #endif | |
1104 | } | |
1105 | ||
1106 | template <unsigned Digits10> | |
1107 | inline std::size_t hash_value(const gmp_float<Digits10>& val) | |
1108 | { | |
1109 | std::size_t result = 0; | |
92f5a8d4 | 1110 | for (int i = 0; i < std::abs(val.data()[0]._mp_size); ++i) |
7c673cae FG |
1111 | boost::hash_combine(result, val.data()[0]._mp_d[i]); |
1112 | boost::hash_combine(result, val.data()[0]._mp_exp); | |
1113 | boost::hash_combine(result, val.data()[0]._mp_size); | |
1114 | return result; | |
1115 | } | |
1116 | ||
1117 | struct gmp_int | |
1118 | { | |
1119 | #ifdef BOOST_HAS_LONG_LONG | |
92f5a8d4 TL |
1120 | typedef mpl::list<long, boost::long_long_type> signed_types; |
1121 | typedef mpl::list<unsigned long, boost::ulong_long_type> unsigned_types; | |
7c673cae | 1122 | #else |
92f5a8d4 TL |
1123 | typedef mpl::list<long> signed_types; |
1124 | typedef mpl::list<unsigned long> unsigned_types; | |
7c673cae | 1125 | #endif |
92f5a8d4 | 1126 | typedef mpl::list<double, long double> float_types; |
7c673cae FG |
1127 | |
1128 | gmp_int() | |
1129 | { | |
1130 | mpz_init(this->m_data); | |
1131 | } | |
1132 | gmp_int(const gmp_int& o) | |
1133 | { | |
92f5a8d4 | 1134 | if (o.m_data[0]._mp_d) |
7c673cae FG |
1135 | mpz_init_set(m_data, o.m_data); |
1136 | else | |
1137 | mpz_init(this->m_data); | |
1138 | } | |
1139 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
1140 | gmp_int(gmp_int&& o) BOOST_NOEXCEPT | |
1141 | { | |
92f5a8d4 | 1142 | m_data[0] = o.m_data[0]; |
7c673cae FG |
1143 | o.m_data[0]._mp_d = 0; |
1144 | } | |
1145 | #endif | |
1146 | explicit gmp_int(const mpf_t val) | |
1147 | { | |
1148 | mpz_init(this->m_data); | |
1149 | mpz_set_f(this->m_data, val); | |
1150 | } | |
1151 | gmp_int(const mpz_t val) | |
1152 | { | |
1153 | mpz_init_set(this->m_data, val); | |
1154 | } | |
1155 | explicit gmp_int(const mpq_t val) | |
1156 | { | |
1157 | mpz_init(this->m_data); | |
1158 | mpz_set_q(this->m_data, val); | |
1159 | } | |
1160 | template <unsigned Digits10> | |
1161 | explicit gmp_int(const gmp_float<Digits10>& o) | |
1162 | { | |
1163 | mpz_init(this->m_data); | |
1164 | mpz_set_f(this->m_data, o.data()); | |
1165 | } | |
1166 | explicit gmp_int(const gmp_rational& o); | |
92f5a8d4 | 1167 | gmp_int& operator=(const gmp_int& o) |
7c673cae | 1168 | { |
92f5a8d4 | 1169 | if (m_data[0]._mp_d == 0) |
7c673cae FG |
1170 | mpz_init(this->m_data); |
1171 | mpz_set(m_data, o.m_data); | |
1172 | return *this; | |
1173 | } | |
1174 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
92f5a8d4 | 1175 | gmp_int& operator=(gmp_int&& o) BOOST_NOEXCEPT |
7c673cae FG |
1176 | { |
1177 | mpz_swap(m_data, o.m_data); | |
1178 | return *this; | |
1179 | } | |
1180 | #endif | |
1181 | #ifdef BOOST_HAS_LONG_LONG | |
1182 | #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) | |
92f5a8d4 | 1183 | gmp_int& operator=(boost::ulong_long_type i) |
7c673cae FG |
1184 | { |
1185 | *this = static_cast<unsigned long>(i); | |
1186 | return *this; | |
1187 | } | |
1188 | #else | |
92f5a8d4 | 1189 | gmp_int& operator=(boost::ulong_long_type i) |
7c673cae | 1190 | { |
92f5a8d4 | 1191 | if (m_data[0]._mp_d == 0) |
7c673cae | 1192 | mpz_init(this->m_data); |
92f5a8d4 TL |
1193 | boost::ulong_long_type mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL); |
1194 | unsigned shift = 0; | |
1195 | mpz_t t; | |
7c673cae FG |
1196 | mpz_set_ui(m_data, 0); |
1197 | mpz_init_set_ui(t, 0); | |
92f5a8d4 | 1198 | while (i) |
7c673cae FG |
1199 | { |
1200 | mpz_set_ui(t, static_cast<unsigned long>(i & mask)); | |
92f5a8d4 | 1201 | if (shift) |
7c673cae FG |
1202 | mpz_mul_2exp(t, t, shift); |
1203 | mpz_add(m_data, m_data, t); | |
1204 | shift += std::numeric_limits<unsigned long>::digits; | |
1205 | i >>= std::numeric_limits<unsigned long>::digits; | |
1206 | } | |
1207 | mpz_clear(t); | |
1208 | return *this; | |
1209 | } | |
1210 | #endif | |
92f5a8d4 | 1211 | gmp_int& operator=(boost::long_long_type i) |
7c673cae | 1212 | { |
92f5a8d4 | 1213 | if (m_data[0]._mp_d == 0) |
7c673cae FG |
1214 | mpz_init(this->m_data); |
1215 | bool neg = i < 0; | |
92f5a8d4 TL |
1216 | *this = boost::multiprecision::detail::unsigned_abs(i); |
1217 | if (neg) | |
7c673cae FG |
1218 | mpz_neg(m_data, m_data); |
1219 | return *this; | |
1220 | } | |
20effc67 TL |
1221 | #endif |
1222 | #ifdef BOOST_HAS_INT128 | |
1223 | gmp_int& operator=(unsigned __int128 i) | |
1224 | { | |
1225 | if (m_data[0]._mp_d == 0) | |
1226 | mpz_init(this->m_data); | |
1227 | unsigned __int128 mask = ((((1uLL << (std::numeric_limits<unsigned long>::digits - 1)) - 1) << 1) | 1uLL); | |
1228 | unsigned shift = 0; | |
1229 | mpz_t t; | |
1230 | mpz_set_ui(m_data, 0); | |
1231 | mpz_init_set_ui(t, 0); | |
1232 | while (i) | |
1233 | { | |
1234 | mpz_set_ui(t, static_cast<unsigned long>(i & mask)); | |
1235 | if (shift) | |
1236 | mpz_mul_2exp(t, t, shift); | |
1237 | mpz_add(m_data, m_data, t); | |
1238 | shift += std::numeric_limits<unsigned long>::digits; | |
1239 | i >>= std::numeric_limits<unsigned long>::digits; | |
1240 | } | |
1241 | mpz_clear(t); | |
1242 | return *this; | |
1243 | } | |
1244 | gmp_int& operator=(__int128 i) | |
1245 | { | |
1246 | if (m_data[0]._mp_d == 0) | |
1247 | mpz_init(this->m_data); | |
1248 | bool neg = i < 0; | |
1249 | *this = boost::multiprecision::detail::unsigned_abs(i); | |
1250 | if (neg) | |
1251 | mpz_neg(m_data, m_data); | |
1252 | return *this; | |
1253 | } | |
7c673cae | 1254 | #endif |
92f5a8d4 | 1255 | gmp_int& operator=(unsigned long i) |
7c673cae | 1256 | { |
92f5a8d4 | 1257 | if (m_data[0]._mp_d == 0) |
7c673cae FG |
1258 | mpz_init(this->m_data); |
1259 | mpz_set_ui(m_data, i); | |
1260 | return *this; | |
1261 | } | |
92f5a8d4 | 1262 | gmp_int& operator=(long i) |
7c673cae | 1263 | { |
92f5a8d4 | 1264 | if (m_data[0]._mp_d == 0) |
7c673cae FG |
1265 | mpz_init(this->m_data); |
1266 | mpz_set_si(m_data, i); | |
1267 | return *this; | |
1268 | } | |
92f5a8d4 | 1269 | gmp_int& operator=(double d) |
7c673cae | 1270 | { |
92f5a8d4 | 1271 | if (m_data[0]._mp_d == 0) |
7c673cae FG |
1272 | mpz_init(this->m_data); |
1273 | mpz_set_d(m_data, d); | |
1274 | return *this; | |
1275 | } | |
92f5a8d4 | 1276 | gmp_int& operator=(long double a) |
7c673cae | 1277 | { |
92f5a8d4 | 1278 | using std::floor; |
7c673cae FG |
1279 | using std::frexp; |
1280 | using std::ldexp; | |
7c673cae | 1281 | |
92f5a8d4 | 1282 | if (m_data[0]._mp_d == 0) |
7c673cae FG |
1283 | mpz_init(this->m_data); |
1284 | ||
92f5a8d4 TL |
1285 | if (a == 0) |
1286 | { | |
7c673cae FG |
1287 | mpz_set_si(m_data, 0); |
1288 | return *this; | |
1289 | } | |
1290 | ||
92f5a8d4 TL |
1291 | if (a == 1) |
1292 | { | |
7c673cae FG |
1293 | mpz_set_si(m_data, 1); |
1294 | return *this; | |
1295 | } | |
1296 | ||
1297 | BOOST_ASSERT(!(boost::math::isinf)(a)); | |
1298 | BOOST_ASSERT(!(boost::math::isnan)(a)); | |
1299 | ||
92f5a8d4 | 1300 | int e; |
7c673cae FG |
1301 | long double f, term; |
1302 | mpz_set_ui(m_data, 0u); | |
1303 | ||
1304 | f = frexp(a, &e); | |
1305 | ||
1306 | static const int shift = std::numeric_limits<int>::digits - 1; | |
1307 | ||
92f5a8d4 | 1308 | while (f) |
7c673cae FG |
1309 | { |
1310 | // extract int sized bits from f: | |
92f5a8d4 | 1311 | f = ldexp(f, shift); |
7c673cae FG |
1312 | term = floor(f); |
1313 | e -= shift; | |
1314 | mpz_mul_2exp(m_data, m_data, shift); | |
92f5a8d4 | 1315 | if (term > 0) |
7c673cae FG |
1316 | mpz_add_ui(m_data, m_data, static_cast<unsigned>(term)); |
1317 | else | |
1318 | mpz_sub_ui(m_data, m_data, static_cast<unsigned>(-term)); | |
1319 | f -= term; | |
1320 | } | |
92f5a8d4 | 1321 | if (e > 0) |
7c673cae | 1322 | mpz_mul_2exp(m_data, m_data, e); |
92f5a8d4 | 1323 | else if (e < 0) |
7c673cae FG |
1324 | mpz_div_2exp(m_data, m_data, -e); |
1325 | return *this; | |
1326 | } | |
92f5a8d4 | 1327 | gmp_int& operator=(const char* s) |
7c673cae | 1328 | { |
92f5a8d4 | 1329 | if (m_data[0]._mp_d == 0) |
7c673cae | 1330 | mpz_init(this->m_data); |
92f5a8d4 TL |
1331 | std::size_t n = s ? std::strlen(s) : 0; |
1332 | int radix = 10; | |
1333 | if (n && (*s == '0')) | |
7c673cae | 1334 | { |
92f5a8d4 | 1335 | if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) |
7c673cae FG |
1336 | { |
1337 | radix = 16; | |
92f5a8d4 | 1338 | s += 2; |
7c673cae FG |
1339 | n -= 2; |
1340 | } | |
1341 | else | |
1342 | { | |
1343 | radix = 8; | |
1344 | n -= 1; | |
1345 | } | |
1346 | } | |
92f5a8d4 | 1347 | if (n) |
7c673cae | 1348 | { |
92f5a8d4 | 1349 | if (0 != mpz_set_str(m_data, s, radix)) |
7c673cae FG |
1350 | BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid integer."))); |
1351 | } | |
1352 | else | |
1353 | mpz_set_ui(m_data, 0); | |
1354 | return *this; | |
1355 | } | |
1356 | gmp_int& operator=(const mpf_t val) | |
1357 | { | |
92f5a8d4 | 1358 | if (m_data[0]._mp_d == 0) |
7c673cae FG |
1359 | mpz_init(this->m_data); |
1360 | mpz_set_f(this->m_data, val); | |
1361 | return *this; | |
1362 | } | |
1363 | gmp_int& operator=(const mpz_t val) | |
1364 | { | |
92f5a8d4 | 1365 | if (m_data[0]._mp_d == 0) |
7c673cae FG |
1366 | mpz_init(this->m_data); |
1367 | mpz_set(this->m_data, val); | |
1368 | return *this; | |
1369 | } | |
1370 | gmp_int& operator=(const mpq_t val) | |
1371 | { | |
92f5a8d4 | 1372 | if (m_data[0]._mp_d == 0) |
7c673cae FG |
1373 | mpz_init(this->m_data); |
1374 | mpz_set_q(this->m_data, val); | |
1375 | return *this; | |
1376 | } | |
1377 | template <unsigned Digits10> | |
1378 | gmp_int& operator=(const gmp_float<Digits10>& o) | |
1379 | { | |
92f5a8d4 | 1380 | if (m_data[0]._mp_d == 0) |
7c673cae FG |
1381 | mpz_init(this->m_data); |
1382 | mpz_set_f(this->m_data, o.data()); | |
1383 | return *this; | |
1384 | } | |
1385 | gmp_int& operator=(const gmp_rational& o); | |
92f5a8d4 | 1386 | void swap(gmp_int& o) |
7c673cae FG |
1387 | { |
1388 | mpz_swap(m_data, o.m_data); | |
1389 | } | |
92f5a8d4 | 1390 | std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f) const |
7c673cae FG |
1391 | { |
1392 | BOOST_ASSERT(m_data[0]._mp_d); | |
1393 | ||
1394 | int base = 10; | |
92f5a8d4 | 1395 | if ((f & std::ios_base::oct) == std::ios_base::oct) |
7c673cae | 1396 | base = 8; |
92f5a8d4 | 1397 | else if ((f & std::ios_base::hex) == std::ios_base::hex) |
7c673cae FG |
1398 | base = 16; |
1399 | // | |
1400 | // sanity check, bases 8 and 16 are only available for positive numbers: | |
1401 | // | |
92f5a8d4 | 1402 | if ((base != 10) && (mpz_sgn(m_data) < 0)) |
7c673cae | 1403 | BOOST_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers")); |
92f5a8d4 TL |
1404 | void* (*alloc_func_ptr)(size_t); |
1405 | void* (*realloc_func_ptr)(void*, size_t, size_t); | |
1406 | void (*free_func_ptr)(void*, size_t); | |
1407 | const char* ps = mpz_get_str(0, base, m_data); | |
1408 | std::string s = ps; | |
7c673cae FG |
1409 | mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); |
1410 | (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); | |
92f5a8d4 TL |
1411 | if (f & std::ios_base::uppercase) |
1412 | for (size_t i = 0; i < s.length(); ++i) | |
1413 | s[i] = std::toupper(s[i]); | |
1414 | if ((base != 10) && (f & std::ios_base::showbase)) | |
7c673cae | 1415 | { |
92f5a8d4 TL |
1416 | int pos = s[0] == '-' ? 1 : 0; |
1417 | const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x"; | |
7c673cae FG |
1418 | s.insert(static_cast<std::string::size_type>(pos), pp); |
1419 | } | |
92f5a8d4 | 1420 | if ((f & std::ios_base::showpos) && (s[0] != '-')) |
7c673cae FG |
1421 | s.insert(static_cast<std::string::size_type>(0), 1, '+'); |
1422 | ||
1423 | return s; | |
1424 | } | |
1425 | ~gmp_int() BOOST_NOEXCEPT | |
1426 | { | |
92f5a8d4 | 1427 | if (m_data[0]._mp_d) |
7c673cae FG |
1428 | mpz_clear(m_data); |
1429 | } | |
1430 | void negate() BOOST_NOEXCEPT | |
1431 | { | |
1432 | BOOST_ASSERT(m_data[0]._mp_d); | |
1433 | mpz_neg(m_data, m_data); | |
1434 | } | |
92f5a8d4 | 1435 | int compare(const gmp_int& o) const BOOST_NOEXCEPT |
7c673cae FG |
1436 | { |
1437 | BOOST_ASSERT(m_data[0]._mp_d && o.m_data[0]._mp_d); | |
1438 | return mpz_cmp(m_data, o.m_data); | |
1439 | } | |
92f5a8d4 | 1440 | int compare(long i) const BOOST_NOEXCEPT |
7c673cae FG |
1441 | { |
1442 | BOOST_ASSERT(m_data[0]._mp_d); | |
1443 | return mpz_cmp_si(m_data, i); | |
1444 | } | |
92f5a8d4 | 1445 | int compare(unsigned long i) const BOOST_NOEXCEPT |
7c673cae FG |
1446 | { |
1447 | BOOST_ASSERT(m_data[0]._mp_d); | |
1448 | return mpz_cmp_ui(m_data, i); | |
1449 | } | |
1450 | template <class V> | |
92f5a8d4 | 1451 | int compare(V v) const |
7c673cae FG |
1452 | { |
1453 | gmp_int d; | |
1454 | d = v; | |
1455 | return compare(d); | |
1456 | } | |
1457 | mpz_t& data() BOOST_NOEXCEPT | |
1458 | { | |
1459 | BOOST_ASSERT(m_data[0]._mp_d); | |
1460 | return m_data; | |
1461 | } | |
92f5a8d4 | 1462 | const mpz_t& data() const BOOST_NOEXCEPT |
7c673cae FG |
1463 | { |
1464 | BOOST_ASSERT(m_data[0]._mp_d); | |
1465 | return m_data; | |
1466 | } | |
92f5a8d4 TL |
1467 | |
1468 | protected: | |
7c673cae FG |
1469 | mpz_t m_data; |
1470 | }; | |
1471 | ||
1472 | template <class T> | |
1473 | inline typename enable_if<is_arithmetic<T>, bool>::type eval_eq(const gmp_int& a, const T& b) | |
1474 | { | |
1475 | return a.compare(b) == 0; | |
1476 | } | |
1477 | template <class T> | |
1478 | inline typename enable_if<is_arithmetic<T>, bool>::type eval_lt(const gmp_int& a, const T& b) | |
1479 | { | |
1480 | return a.compare(b) < 0; | |
1481 | } | |
1482 | template <class T> | |
1483 | inline typename enable_if<is_arithmetic<T>, bool>::type eval_gt(const gmp_int& a, const T& b) | |
1484 | { | |
1485 | return a.compare(b) > 0; | |
1486 | } | |
1487 | ||
1488 | inline bool eval_is_zero(const gmp_int& val) | |
1489 | { | |
1490 | return mpz_sgn(val.data()) == 0; | |
1491 | } | |
1492 | inline void eval_add(gmp_int& t, const gmp_int& o) | |
1493 | { | |
1494 | mpz_add(t.data(), t.data(), o.data()); | |
1495 | } | |
1496 | inline void eval_multiply_add(gmp_int& t, const gmp_int& a, const gmp_int& b) | |
1497 | { | |
1498 | mpz_addmul(t.data(), a.data(), b.data()); | |
1499 | } | |
1500 | inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, const gmp_int& b) | |
1501 | { | |
1502 | mpz_submul(t.data(), a.data(), b.data()); | |
1503 | } | |
1504 | inline void eval_subtract(gmp_int& t, const gmp_int& o) | |
1505 | { | |
1506 | mpz_sub(t.data(), t.data(), o.data()); | |
1507 | } | |
1508 | inline void eval_multiply(gmp_int& t, const gmp_int& o) | |
1509 | { | |
1510 | mpz_mul(t.data(), t.data(), o.data()); | |
1511 | } | |
1512 | inline void eval_divide(gmp_int& t, const gmp_int& o) | |
1513 | { | |
92f5a8d4 | 1514 | if (eval_is_zero(o)) |
7c673cae FG |
1515 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
1516 | mpz_tdiv_q(t.data(), t.data(), o.data()); | |
1517 | } | |
1518 | inline void eval_modulus(gmp_int& t, const gmp_int& o) | |
1519 | { | |
1520 | mpz_tdiv_r(t.data(), t.data(), o.data()); | |
1521 | } | |
1522 | inline void eval_add(gmp_int& t, unsigned long i) | |
1523 | { | |
1524 | mpz_add_ui(t.data(), t.data(), i); | |
1525 | } | |
1526 | inline void eval_multiply_add(gmp_int& t, const gmp_int& a, unsigned long i) | |
1527 | { | |
1528 | mpz_addmul_ui(t.data(), a.data(), i); | |
1529 | } | |
1530 | inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, unsigned long i) | |
1531 | { | |
1532 | mpz_submul_ui(t.data(), a.data(), i); | |
1533 | } | |
1534 | inline void eval_subtract(gmp_int& t, unsigned long i) | |
1535 | { | |
1536 | mpz_sub_ui(t.data(), t.data(), i); | |
1537 | } | |
1538 | inline void eval_multiply(gmp_int& t, unsigned long i) | |
1539 | { | |
1540 | mpz_mul_ui(t.data(), t.data(), i); | |
1541 | } | |
1542 | inline void eval_modulus(gmp_int& t, unsigned long i) | |
1543 | { | |
1544 | mpz_tdiv_r_ui(t.data(), t.data(), i); | |
1545 | } | |
1546 | inline void eval_divide(gmp_int& t, unsigned long i) | |
1547 | { | |
92f5a8d4 | 1548 | if (i == 0) |
7c673cae FG |
1549 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
1550 | mpz_tdiv_q_ui(t.data(), t.data(), i); | |
1551 | } | |
1552 | inline void eval_add(gmp_int& t, long i) | |
1553 | { | |
92f5a8d4 | 1554 | if (i > 0) |
7c673cae FG |
1555 | mpz_add_ui(t.data(), t.data(), i); |
1556 | else | |
1557 | mpz_sub_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
1558 | } | |
1559 | inline void eval_multiply_add(gmp_int& t, const gmp_int& a, long i) | |
1560 | { | |
92f5a8d4 | 1561 | if (i > 0) |
7c673cae FG |
1562 | mpz_addmul_ui(t.data(), a.data(), i); |
1563 | else | |
1564 | mpz_submul_ui(t.data(), a.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
1565 | } | |
1566 | inline void eval_multiply_subtract(gmp_int& t, const gmp_int& a, long i) | |
1567 | { | |
92f5a8d4 | 1568 | if (i > 0) |
7c673cae FG |
1569 | mpz_submul_ui(t.data(), a.data(), i); |
1570 | else | |
1571 | mpz_addmul_ui(t.data(), a.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
1572 | } | |
1573 | inline void eval_subtract(gmp_int& t, long i) | |
1574 | { | |
92f5a8d4 | 1575 | if (i > 0) |
7c673cae FG |
1576 | mpz_sub_ui(t.data(), t.data(), i); |
1577 | else | |
1578 | mpz_add_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
1579 | } | |
1580 | inline void eval_multiply(gmp_int& t, long i) | |
1581 | { | |
1582 | mpz_mul_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
92f5a8d4 | 1583 | if (i < 0) |
7c673cae FG |
1584 | mpz_neg(t.data(), t.data()); |
1585 | } | |
1586 | inline void eval_modulus(gmp_int& t, long i) | |
1587 | { | |
1588 | mpz_tdiv_r_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
1589 | } | |
1590 | inline void eval_divide(gmp_int& t, long i) | |
1591 | { | |
92f5a8d4 | 1592 | if (i == 0) |
7c673cae FG |
1593 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
1594 | mpz_tdiv_q_ui(t.data(), t.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
92f5a8d4 | 1595 | if (i < 0) |
7c673cae FG |
1596 | mpz_neg(t.data(), t.data()); |
1597 | } | |
1598 | template <class UI> | |
1599 | inline void eval_left_shift(gmp_int& t, UI i) | |
1600 | { | |
1601 | mpz_mul_2exp(t.data(), t.data(), static_cast<unsigned long>(i)); | |
1602 | } | |
1603 | template <class UI> | |
1604 | inline void eval_right_shift(gmp_int& t, UI i) | |
1605 | { | |
1606 | mpz_fdiv_q_2exp(t.data(), t.data(), static_cast<unsigned long>(i)); | |
1607 | } | |
1608 | template <class UI> | |
1609 | inline void eval_left_shift(gmp_int& t, const gmp_int& v, UI i) | |
1610 | { | |
1611 | mpz_mul_2exp(t.data(), v.data(), static_cast<unsigned long>(i)); | |
1612 | } | |
1613 | template <class UI> | |
1614 | inline void eval_right_shift(gmp_int& t, const gmp_int& v, UI i) | |
1615 | { | |
1616 | mpz_fdiv_q_2exp(t.data(), v.data(), static_cast<unsigned long>(i)); | |
1617 | } | |
1618 | ||
1619 | inline void eval_bitwise_and(gmp_int& result, const gmp_int& v) | |
1620 | { | |
1621 | mpz_and(result.data(), result.data(), v.data()); | |
1622 | } | |
1623 | ||
1624 | inline void eval_bitwise_or(gmp_int& result, const gmp_int& v) | |
1625 | { | |
1626 | mpz_ior(result.data(), result.data(), v.data()); | |
1627 | } | |
1628 | ||
1629 | inline void eval_bitwise_xor(gmp_int& result, const gmp_int& v) | |
1630 | { | |
1631 | mpz_xor(result.data(), result.data(), v.data()); | |
1632 | } | |
1633 | ||
1634 | inline void eval_add(gmp_int& t, const gmp_int& p, const gmp_int& o) | |
1635 | { | |
1636 | mpz_add(t.data(), p.data(), o.data()); | |
1637 | } | |
1638 | inline void eval_subtract(gmp_int& t, const gmp_int& p, const gmp_int& o) | |
1639 | { | |
1640 | mpz_sub(t.data(), p.data(), o.data()); | |
1641 | } | |
1642 | inline void eval_multiply(gmp_int& t, const gmp_int& p, const gmp_int& o) | |
1643 | { | |
1644 | mpz_mul(t.data(), p.data(), o.data()); | |
1645 | } | |
1646 | inline void eval_divide(gmp_int& t, const gmp_int& p, const gmp_int& o) | |
1647 | { | |
92f5a8d4 | 1648 | if (eval_is_zero(o)) |
7c673cae FG |
1649 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
1650 | mpz_tdiv_q(t.data(), p.data(), o.data()); | |
1651 | } | |
1652 | inline void eval_modulus(gmp_int& t, const gmp_int& p, const gmp_int& o) | |
1653 | { | |
1654 | mpz_tdiv_r(t.data(), p.data(), o.data()); | |
1655 | } | |
1656 | inline void eval_add(gmp_int& t, const gmp_int& p, unsigned long i) | |
1657 | { | |
1658 | mpz_add_ui(t.data(), p.data(), i); | |
1659 | } | |
1660 | inline void eval_subtract(gmp_int& t, const gmp_int& p, unsigned long i) | |
1661 | { | |
1662 | mpz_sub_ui(t.data(), p.data(), i); | |
1663 | } | |
1664 | inline void eval_multiply(gmp_int& t, const gmp_int& p, unsigned long i) | |
1665 | { | |
1666 | mpz_mul_ui(t.data(), p.data(), i); | |
1667 | } | |
1668 | inline void eval_modulus(gmp_int& t, const gmp_int& p, unsigned long i) | |
1669 | { | |
1670 | mpz_tdiv_r_ui(t.data(), p.data(), i); | |
1671 | } | |
1672 | inline void eval_divide(gmp_int& t, const gmp_int& p, unsigned long i) | |
1673 | { | |
92f5a8d4 | 1674 | if (i == 0) |
7c673cae FG |
1675 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
1676 | mpz_tdiv_q_ui(t.data(), p.data(), i); | |
1677 | } | |
1678 | inline void eval_add(gmp_int& t, const gmp_int& p, long i) | |
1679 | { | |
92f5a8d4 | 1680 | if (i > 0) |
7c673cae FG |
1681 | mpz_add_ui(t.data(), p.data(), i); |
1682 | else | |
1683 | mpz_sub_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
1684 | } | |
1685 | inline void eval_subtract(gmp_int& t, const gmp_int& p, long i) | |
1686 | { | |
92f5a8d4 | 1687 | if (i > 0) |
7c673cae FG |
1688 | mpz_sub_ui(t.data(), p.data(), i); |
1689 | else | |
1690 | mpz_add_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
1691 | } | |
1692 | inline void eval_multiply(gmp_int& t, const gmp_int& p, long i) | |
1693 | { | |
1694 | mpz_mul_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
92f5a8d4 | 1695 | if (i < 0) |
7c673cae FG |
1696 | mpz_neg(t.data(), t.data()); |
1697 | } | |
1698 | inline void eval_modulus(gmp_int& t, const gmp_int& p, long i) | |
1699 | { | |
1700 | mpz_tdiv_r_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
1701 | } | |
1702 | inline void eval_divide(gmp_int& t, const gmp_int& p, long i) | |
1703 | { | |
92f5a8d4 | 1704 | if (i == 0) |
7c673cae FG |
1705 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
1706 | mpz_tdiv_q_ui(t.data(), p.data(), boost::multiprecision::detail::unsigned_abs(i)); | |
92f5a8d4 | 1707 | if (i < 0) |
7c673cae FG |
1708 | mpz_neg(t.data(), t.data()); |
1709 | } | |
1710 | ||
1711 | inline void eval_bitwise_and(gmp_int& result, const gmp_int& u, const gmp_int& v) | |
1712 | { | |
1713 | mpz_and(result.data(), u.data(), v.data()); | |
1714 | } | |
1715 | ||
1716 | inline void eval_bitwise_or(gmp_int& result, const gmp_int& u, const gmp_int& v) | |
1717 | { | |
1718 | mpz_ior(result.data(), u.data(), v.data()); | |
1719 | } | |
1720 | ||
1721 | inline void eval_bitwise_xor(gmp_int& result, const gmp_int& u, const gmp_int& v) | |
1722 | { | |
1723 | mpz_xor(result.data(), u.data(), v.data()); | |
1724 | } | |
1725 | ||
1726 | inline void eval_complement(gmp_int& result, const gmp_int& u) | |
1727 | { | |
1728 | mpz_com(result.data(), u.data()); | |
1729 | } | |
1730 | ||
1731 | inline int eval_get_sign(const gmp_int& val) | |
1732 | { | |
1733 | return mpz_sgn(val.data()); | |
1734 | } | |
1735 | inline void eval_convert_to(unsigned long* result, const gmp_int& val) | |
1736 | { | |
11fdf7f2 TL |
1737 | if (mpz_sgn(val.data()) < 0) |
1738 | { | |
1739 | BOOST_THROW_EXCEPTION(std::range_error("Conversion from negative integer to an unsigned type results in undefined behaviour")); | |
1740 | } | |
7c673cae | 1741 | else |
11fdf7f2 | 1742 | *result = (unsigned long)mpz_get_ui(val.data()); |
7c673cae FG |
1743 | } |
1744 | inline void eval_convert_to(long* result, const gmp_int& val) | |
1745 | { | |
92f5a8d4 | 1746 | if (0 == mpz_fits_slong_p(val.data())) |
7c673cae | 1747 | { |
92f5a8d4 | 1748 | *result = mpz_sgn(val.data()) < 0 ? (std::numeric_limits<long>::min)() : (std::numeric_limits<long>::max)(); |
7c673cae FG |
1749 | } |
1750 | else | |
11fdf7f2 | 1751 | *result = (signed long)mpz_get_si(val.data()); |
7c673cae FG |
1752 | } |
1753 | inline void eval_convert_to(double* result, const gmp_int& val) | |
1754 | { | |
1755 | *result = mpz_get_d(val.data()); | |
1756 | } | |
20effc67 TL |
1757 | #ifdef BOOST_HAS_LONG_LONG |
1758 | inline void eval_convert_to(boost::ulong_long_type* result, const gmp_int& val) | |
1759 | { | |
1760 | if (mpz_sgn(val.data()) < 0) | |
1761 | { | |
1762 | BOOST_THROW_EXCEPTION(std::range_error("Conversion from negative integer to an unsigned type results in undefined behaviour")); | |
1763 | } | |
1764 | *result = 0; | |
1765 | gmp_int t(val); | |
1766 | unsigned parts = sizeof(boost::ulong_long_type) / sizeof(unsigned long); | |
1767 | ||
1768 | for (unsigned i = 0; i < parts; ++i) | |
1769 | { | |
1770 | boost::ulong_long_type part = mpz_get_ui(t.data()); | |
1771 | if (i) | |
1772 | *result |= part << (i * sizeof(unsigned long) * CHAR_BIT); | |
1773 | else | |
1774 | *result = part; | |
1775 | mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT); | |
1776 | } | |
1777 | } | |
1778 | inline void eval_convert_to(boost::long_long_type* result, const gmp_int& val) | |
1779 | { | |
1780 | int s = mpz_sgn(val.data()); | |
1781 | *result = 0; | |
1782 | gmp_int t(val); | |
1783 | unsigned parts = sizeof(boost::ulong_long_type) / sizeof(unsigned long); | |
1784 | boost::ulong_long_type unsigned_result = 0; | |
1785 | ||
1786 | for (unsigned i = 0; i < parts; ++i) | |
1787 | { | |
1788 | boost::ulong_long_type part = mpz_get_ui(t.data()); | |
1789 | if (i) | |
1790 | unsigned_result |= part << (i * sizeof(unsigned long) * CHAR_BIT); | |
1791 | else | |
1792 | unsigned_result = part; | |
1793 | mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT); | |
1794 | } | |
1795 | // | |
1796 | // Overflow check: | |
1797 | // | |
1798 | bool overflow = false; | |
1799 | if (mpz_sgn(t.data())) | |
1800 | { | |
1801 | overflow = true; | |
1802 | } | |
1803 | if ((s > 0) && (unsigned_result > static_cast<boost::ulong_long_type>((std::numeric_limits<boost::long_long_type>::max)()))) | |
1804 | overflow = true; | |
1805 | if((s < 0) && (unsigned_result > 1u - static_cast<boost::ulong_long_type>((std::numeric_limits<boost::long_long_type>::min)() + 1))) | |
1806 | overflow = true; | |
1807 | if(overflow) | |
1808 | *result = s < 0 ? (std::numeric_limits<boost::long_long_type>::min)() : (std::numeric_limits<boost::long_long_type>::max)(); | |
1809 | else | |
1810 | *result = s < 0 ? -boost::long_long_type(unsigned_result - 1) - 1 : unsigned_result; | |
1811 | } | |
1812 | #endif | |
1813 | #ifdef BOOST_HAS_INT128 | |
1814 | inline void eval_convert_to(unsigned __int128* result, const gmp_int& val) | |
1815 | { | |
1816 | if (mpz_sgn(val.data()) < 0) | |
1817 | { | |
1818 | BOOST_THROW_EXCEPTION(std::range_error("Conversion from negative integer to an unsigned type results in undefined behaviour")); | |
1819 | } | |
1820 | *result = 0; | |
1821 | gmp_int t(val); | |
1822 | unsigned parts = sizeof(unsigned __int128) / sizeof(unsigned long); | |
7c673cae | 1823 | |
20effc67 TL |
1824 | for (unsigned i = 0; i < parts; ++i) |
1825 | { | |
1826 | unsigned __int128 part = mpz_get_ui(t.data()); | |
1827 | if (i) | |
1828 | *result |= part << (i * sizeof(unsigned long) * CHAR_BIT); | |
1829 | else | |
1830 | *result = part; | |
1831 | mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT); | |
1832 | } | |
1833 | } | |
1834 | inline void eval_convert_to(__int128* result, const gmp_int& val) | |
1835 | { | |
1836 | int s = mpz_sgn(val.data()); | |
1837 | *result = 0; | |
1838 | gmp_int t(val); | |
1839 | unsigned parts = sizeof(unsigned __int128) / sizeof(unsigned long); | |
1840 | unsigned __int128 unsigned_result = 0; | |
1841 | ||
1842 | for (unsigned i = 0; i < parts; ++i) | |
1843 | { | |
1844 | unsigned __int128 part = mpz_get_ui(t.data()); | |
1845 | if (i) | |
1846 | unsigned_result |= part << (i * sizeof(unsigned long) * CHAR_BIT); | |
1847 | else | |
1848 | unsigned_result = part; | |
1849 | mpz_tdiv_q_2exp(t.data(), t.data(), sizeof(unsigned long) * CHAR_BIT); | |
1850 | } | |
1851 | // | |
1852 | // Overflow check: | |
1853 | // | |
1854 | static const __int128 int128_max = static_cast<__int128>((static_cast<unsigned __int128>(1u) << 127) - 1); | |
1855 | static const __int128 int128_min = (static_cast<unsigned __int128>(1u) << 127); | |
1856 | bool overflow = false; | |
1857 | if (mpz_sgn(t.data())) | |
1858 | { | |
1859 | overflow = true; | |
1860 | } | |
1861 | if ((s > 0) && (unsigned_result > static_cast<unsigned __int128>(int128_max))) | |
1862 | overflow = true; | |
1863 | if ((s < 0) && (unsigned_result > 1u - static_cast<unsigned __int128>(int128_min + 1))) | |
1864 | overflow = true; | |
1865 | if (overflow) | |
1866 | *result = s < 0 ? int128_min : int128_max; | |
1867 | else | |
1868 | *result = s < 0 ? -__int128(unsigned_result - 1) - 1 : unsigned_result; | |
1869 | } | |
1870 | #endif | |
7c673cae FG |
1871 | inline void eval_abs(gmp_int& result, const gmp_int& val) |
1872 | { | |
1873 | mpz_abs(result.data(), val.data()); | |
1874 | } | |
1875 | ||
1876 | inline void eval_gcd(gmp_int& result, const gmp_int& a, const gmp_int& b) | |
1877 | { | |
1878 | mpz_gcd(result.data(), a.data(), b.data()); | |
1879 | } | |
1880 | inline void eval_lcm(gmp_int& result, const gmp_int& a, const gmp_int& b) | |
1881 | { | |
1882 | mpz_lcm(result.data(), a.data(), b.data()); | |
1883 | } | |
1884 | template <class I> | |
1885 | inline typename enable_if_c<(is_unsigned<I>::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b) | |
1886 | { | |
1887 | mpz_gcd_ui(result.data(), a.data(), b); | |
1888 | } | |
1889 | template <class I> | |
1890 | inline typename enable_if_c<(is_unsigned<I>::value && (sizeof(I) <= sizeof(unsigned long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b) | |
1891 | { | |
1892 | mpz_lcm_ui(result.data(), a.data(), b); | |
1893 | } | |
1894 | template <class I> | |
1895 | inline typename enable_if_c<(is_signed<I>::value && (sizeof(I) <= sizeof(long)))>::type eval_gcd(gmp_int& result, const gmp_int& a, const I b) | |
1896 | { | |
1897 | mpz_gcd_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b)); | |
1898 | } | |
1899 | template <class I> | |
1900 | inline typename enable_if_c<is_signed<I>::value && ((sizeof(I) <= sizeof(long)))>::type eval_lcm(gmp_int& result, const gmp_int& a, const I b) | |
1901 | { | |
1902 | mpz_lcm_ui(result.data(), a.data(), boost::multiprecision::detail::unsigned_abs(b)); | |
1903 | } | |
1904 | ||
1905 | inline void eval_integer_sqrt(gmp_int& s, gmp_int& r, const gmp_int& x) | |
1906 | { | |
1907 | mpz_sqrtrem(s.data(), r.data(), x.data()); | |
1908 | } | |
1909 | ||
1910 | inline unsigned eval_lsb(const gmp_int& val) | |
1911 | { | |
1912 | int c = eval_get_sign(val); | |
92f5a8d4 | 1913 | if (c == 0) |
7c673cae FG |
1914 | { |
1915 | BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); | |
1916 | } | |
92f5a8d4 | 1917 | if (c < 0) |
7c673cae FG |
1918 | { |
1919 | BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); | |
1920 | } | |
1921 | return static_cast<unsigned>(mpz_scan1(val.data(), 0)); | |
1922 | } | |
1923 | ||
1924 | inline unsigned eval_msb(const gmp_int& val) | |
1925 | { | |
1926 | int c = eval_get_sign(val); | |
92f5a8d4 | 1927 | if (c == 0) |
7c673cae FG |
1928 | { |
1929 | BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); | |
1930 | } | |
92f5a8d4 | 1931 | if (c < 0) |
7c673cae FG |
1932 | { |
1933 | BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); | |
1934 | } | |
1935 | return static_cast<unsigned>(mpz_sizeinbase(val.data(), 2) - 1); | |
1936 | } | |
1937 | ||
1938 | inline bool eval_bit_test(const gmp_int& val, unsigned index) | |
1939 | { | |
1940 | return mpz_tstbit(val.data(), index) ? true : false; | |
1941 | } | |
1942 | ||
1943 | inline void eval_bit_set(gmp_int& val, unsigned index) | |
1944 | { | |
1945 | mpz_setbit(val.data(), index); | |
1946 | } | |
1947 | ||
1948 | inline void eval_bit_unset(gmp_int& val, unsigned index) | |
1949 | { | |
1950 | mpz_clrbit(val.data(), index); | |
1951 | } | |
1952 | ||
1953 | inline void eval_bit_flip(gmp_int& val, unsigned index) | |
1954 | { | |
1955 | mpz_combit(val.data(), index); | |
1956 | } | |
1957 | ||
1958 | inline void eval_qr(const gmp_int& x, const gmp_int& y, | |
92f5a8d4 | 1959 | gmp_int& q, gmp_int& r) |
7c673cae FG |
1960 | { |
1961 | mpz_tdiv_qr(q.data(), r.data(), x.data(), y.data()); | |
1962 | } | |
1963 | ||
1964 | template <class Integer> | |
1965 | inline typename enable_if<is_unsigned<Integer>, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val) | |
1966 | { | |
11fdf7f2 | 1967 | #if defined(__MPIR_VERSION) && (__MPIR_VERSION >= 3) |
92f5a8d4 | 1968 | if ((sizeof(Integer) <= sizeof(mpir_ui)) || (val <= (std::numeric_limits<mpir_ui>::max)())) |
11fdf7f2 | 1969 | #else |
92f5a8d4 | 1970 | if ((sizeof(Integer) <= sizeof(long)) || (val <= (std::numeric_limits<unsigned long>::max)())) |
11fdf7f2 | 1971 | #endif |
7c673cae | 1972 | { |
11fdf7f2 | 1973 | return static_cast<Integer>(mpz_tdiv_ui(x.data(), val)); |
7c673cae FG |
1974 | } |
1975 | else | |
1976 | { | |
1977 | return default_ops::eval_integer_modulus(x, val); | |
1978 | } | |
1979 | } | |
1980 | template <class Integer> | |
1981 | inline typename enable_if<is_signed<Integer>, Integer>::type eval_integer_modulus(const gmp_int& x, Integer val) | |
1982 | { | |
1983 | return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val)); | |
1984 | } | |
1985 | inline void eval_powm(gmp_int& result, const gmp_int& base, const gmp_int& p, const gmp_int& m) | |
1986 | { | |
92f5a8d4 | 1987 | if (eval_get_sign(p) < 0) |
7c673cae FG |
1988 | { |
1989 | BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); | |
1990 | } | |
1991 | mpz_powm(result.data(), base.data(), p.data(), m.data()); | |
1992 | } | |
1993 | ||
1994 | template <class Integer> | |
1995 | inline typename enable_if< | |
92f5a8d4 TL |
1996 | mpl::and_< |
1997 | is_unsigned<Integer>, | |
1998 | mpl::bool_<sizeof(Integer) <= sizeof(unsigned long)> > >::type | |
1999 | eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m) | |
7c673cae FG |
2000 | { |
2001 | mpz_powm_ui(result.data(), base.data(), p, m.data()); | |
2002 | } | |
2003 | template <class Integer> | |
2004 | inline typename enable_if< | |
92f5a8d4 TL |
2005 | mpl::and_< |
2006 | is_signed<Integer>, | |
2007 | mpl::bool_<sizeof(Integer) <= sizeof(unsigned long)> > >::type | |
2008 | eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m) | |
7c673cae | 2009 | { |
92f5a8d4 | 2010 | if (p < 0) |
7c673cae FG |
2011 | { |
2012 | BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); | |
2013 | } | |
2014 | mpz_powm_ui(result.data(), base.data(), p, m.data()); | |
2015 | } | |
2016 | ||
2017 | inline std::size_t hash_value(const gmp_int& val) | |
2018 | { | |
2019 | // We should really use mpz_limbs_read here, but that's unsupported on older versions: | |
2020 | std::size_t result = 0; | |
92f5a8d4 | 2021 | for (int i = 0; i < std::abs(val.data()[0]._mp_size); ++i) |
7c673cae FG |
2022 | boost::hash_combine(result, val.data()[0]._mp_d[i]); |
2023 | boost::hash_combine(result, val.data()[0]._mp_size); | |
2024 | return result; | |
2025 | } | |
2026 | ||
2027 | struct gmp_rational; | |
2028 | void eval_add(gmp_rational& t, const gmp_rational& o); | |
2029 | ||
2030 | struct gmp_rational | |
2031 | { | |
2032 | #ifdef BOOST_HAS_LONG_LONG | |
92f5a8d4 TL |
2033 | typedef mpl::list<long, boost::long_long_type> signed_types; |
2034 | typedef mpl::list<unsigned long, boost::ulong_long_type> unsigned_types; | |
7c673cae | 2035 | #else |
92f5a8d4 TL |
2036 | typedef mpl::list<long> signed_types; |
2037 | typedef mpl::list<unsigned long> unsigned_types; | |
7c673cae | 2038 | #endif |
92f5a8d4 | 2039 | typedef mpl::list<double, long double> float_types; |
7c673cae FG |
2040 | |
2041 | gmp_rational() | |
2042 | { | |
2043 | mpq_init(this->m_data); | |
2044 | } | |
2045 | gmp_rational(const gmp_rational& o) | |
2046 | { | |
2047 | mpq_init(m_data); | |
92f5a8d4 | 2048 | if (o.m_data[0]._mp_num._mp_d) |
7c673cae FG |
2049 | mpq_set(m_data, o.m_data); |
2050 | } | |
2051 | gmp_rational(const gmp_int& o) | |
2052 | { | |
2053 | mpq_init(m_data); | |
2054 | mpq_set_z(m_data, o.data()); | |
2055 | } | |
2056 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
2057 | gmp_rational(gmp_rational&& o) BOOST_NOEXCEPT | |
2058 | { | |
92f5a8d4 | 2059 | m_data[0] = o.m_data[0]; |
7c673cae FG |
2060 | o.m_data[0]._mp_num._mp_d = 0; |
2061 | o.m_data[0]._mp_den._mp_d = 0; | |
2062 | } | |
2063 | #endif | |
2064 | gmp_rational(const mpq_t o) | |
2065 | { | |
2066 | mpq_init(m_data); | |
2067 | mpq_set(m_data, o); | |
2068 | } | |
2069 | gmp_rational(const mpz_t o) | |
2070 | { | |
2071 | mpq_init(m_data); | |
2072 | mpq_set_z(m_data, o); | |
2073 | } | |
92f5a8d4 | 2074 | gmp_rational& operator=(const gmp_rational& o) |
7c673cae | 2075 | { |
92f5a8d4 | 2076 | if (m_data[0]._mp_den._mp_d == 0) |
7c673cae FG |
2077 | mpq_init(m_data); |
2078 | mpq_set(m_data, o.m_data); | |
2079 | return *this; | |
2080 | } | |
2081 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
92f5a8d4 | 2082 | gmp_rational& operator=(gmp_rational&& o) BOOST_NOEXCEPT |
7c673cae FG |
2083 | { |
2084 | mpq_swap(m_data, o.m_data); | |
2085 | return *this; | |
2086 | } | |
2087 | #endif | |
2088 | #ifdef BOOST_HAS_LONG_LONG | |
2089 | #if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) | |
92f5a8d4 | 2090 | gmp_rational& operator=(boost::ulong_long_type i) |
7c673cae FG |
2091 | { |
2092 | *this = static_cast<unsigned long>(i); | |
2093 | return *this; | |
2094 | } | |
2095 | #else | |
92f5a8d4 | 2096 | gmp_rational& operator=(boost::ulong_long_type i) |
7c673cae | 2097 | { |
92f5a8d4 | 2098 | if (m_data[0]._mp_den._mp_d == 0) |
7c673cae FG |
2099 | mpq_init(m_data); |
2100 | gmp_int zi; | |
2101 | zi = i; | |
2102 | mpq_set_z(m_data, zi.data()); | |
2103 | return *this; | |
2104 | } | |
92f5a8d4 | 2105 | gmp_rational& operator=(boost::long_long_type i) |
7c673cae | 2106 | { |
92f5a8d4 | 2107 | if (m_data[0]._mp_den._mp_d == 0) |
7c673cae FG |
2108 | mpq_init(m_data); |
2109 | bool neg = i < 0; | |
92f5a8d4 TL |
2110 | *this = boost::multiprecision::detail::unsigned_abs(i); |
2111 | if (neg) | |
7c673cae FG |
2112 | mpq_neg(m_data, m_data); |
2113 | return *this; | |
2114 | } | |
2115 | #endif | |
2116 | #endif | |
92f5a8d4 | 2117 | gmp_rational& operator=(unsigned long i) |
7c673cae | 2118 | { |
92f5a8d4 | 2119 | if (m_data[0]._mp_den._mp_d == 0) |
7c673cae FG |
2120 | mpq_init(m_data); |
2121 | mpq_set_ui(m_data, i, 1); | |
2122 | return *this; | |
2123 | } | |
92f5a8d4 | 2124 | gmp_rational& operator=(long i) |
7c673cae | 2125 | { |
92f5a8d4 | 2126 | if (m_data[0]._mp_den._mp_d == 0) |
7c673cae FG |
2127 | mpq_init(m_data); |
2128 | mpq_set_si(m_data, i, 1); | |
2129 | return *this; | |
2130 | } | |
92f5a8d4 | 2131 | gmp_rational& operator=(double d) |
7c673cae | 2132 | { |
92f5a8d4 | 2133 | if (m_data[0]._mp_den._mp_d == 0) |
7c673cae FG |
2134 | mpq_init(m_data); |
2135 | mpq_set_d(m_data, d); | |
2136 | return *this; | |
2137 | } | |
92f5a8d4 | 2138 | gmp_rational& operator=(long double a) |
7c673cae | 2139 | { |
7c673cae FG |
2140 | using default_ops::eval_add; |
2141 | using default_ops::eval_subtract; | |
92f5a8d4 TL |
2142 | using std::floor; |
2143 | using std::frexp; | |
2144 | using std::ldexp; | |
7c673cae | 2145 | |
92f5a8d4 | 2146 | if (m_data[0]._mp_den._mp_d == 0) |
7c673cae FG |
2147 | mpq_init(m_data); |
2148 | ||
92f5a8d4 TL |
2149 | if (a == 0) |
2150 | { | |
7c673cae FG |
2151 | mpq_set_si(m_data, 0, 1); |
2152 | return *this; | |
2153 | } | |
2154 | ||
92f5a8d4 TL |
2155 | if (a == 1) |
2156 | { | |
7c673cae FG |
2157 | mpq_set_si(m_data, 1, 1); |
2158 | return *this; | |
2159 | } | |
2160 | ||
2161 | BOOST_ASSERT(!(boost::math::isinf)(a)); | |
2162 | BOOST_ASSERT(!(boost::math::isnan)(a)); | |
2163 | ||
92f5a8d4 | 2164 | int e; |
7c673cae FG |
2165 | long double f, term; |
2166 | mpq_set_ui(m_data, 0, 1); | |
2167 | mpq_set_ui(m_data, 0u, 1); | |
2168 | gmp_rational t; | |
2169 | ||
2170 | f = frexp(a, &e); | |
2171 | ||
2172 | static const int shift = std::numeric_limits<int>::digits - 1; | |
2173 | ||
92f5a8d4 | 2174 | while (f) |
7c673cae FG |
2175 | { |
2176 | // extract int sized bits from f: | |
92f5a8d4 | 2177 | f = ldexp(f, shift); |
7c673cae FG |
2178 | term = floor(f); |
2179 | e -= shift; | |
2180 | mpq_mul_2exp(m_data, m_data, shift); | |
2181 | t = static_cast<long>(term); | |
2182 | eval_add(*this, t); | |
2183 | f -= term; | |
2184 | } | |
92f5a8d4 | 2185 | if (e > 0) |
7c673cae | 2186 | mpq_mul_2exp(m_data, m_data, e); |
92f5a8d4 | 2187 | else if (e < 0) |
7c673cae FG |
2188 | mpq_div_2exp(m_data, m_data, -e); |
2189 | return *this; | |
2190 | } | |
92f5a8d4 | 2191 | gmp_rational& operator=(const char* s) |
7c673cae | 2192 | { |
92f5a8d4 | 2193 | if (m_data[0]._mp_den._mp_d == 0) |
7c673cae | 2194 | mpq_init(m_data); |
92f5a8d4 | 2195 | if (0 != mpq_set_str(m_data, s, 10)) |
7c673cae FG |
2196 | BOOST_THROW_EXCEPTION(std::runtime_error(std::string("The string \"") + s + std::string("\"could not be interpreted as a valid rational number."))); |
2197 | return *this; | |
2198 | } | |
2199 | gmp_rational& operator=(const gmp_int& o) | |
2200 | { | |
92f5a8d4 | 2201 | if (m_data[0]._mp_den._mp_d == 0) |
7c673cae FG |
2202 | mpq_init(m_data); |
2203 | mpq_set_z(m_data, o.data()); | |
2204 | return *this; | |
2205 | } | |
2206 | gmp_rational& operator=(const mpq_t o) | |
2207 | { | |
92f5a8d4 | 2208 | if (m_data[0]._mp_den._mp_d == 0) |
7c673cae FG |
2209 | mpq_init(m_data); |
2210 | mpq_set(m_data, o); | |
2211 | return *this; | |
2212 | } | |
2213 | gmp_rational& operator=(const mpz_t o) | |
2214 | { | |
92f5a8d4 | 2215 | if (m_data[0]._mp_den._mp_d == 0) |
7c673cae FG |
2216 | mpq_init(m_data); |
2217 | mpq_set_z(m_data, o); | |
2218 | return *this; | |
2219 | } | |
2220 | void swap(gmp_rational& o) | |
2221 | { | |
2222 | mpq_swap(m_data, o.m_data); | |
2223 | } | |
92f5a8d4 | 2224 | std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags /*f*/) const |
7c673cae FG |
2225 | { |
2226 | BOOST_ASSERT(m_data[0]._mp_num._mp_d); | |
2227 | // TODO make a better job of this including handling of f!! | |
92f5a8d4 TL |
2228 | void* (*alloc_func_ptr)(size_t); |
2229 | void* (*realloc_func_ptr)(void*, size_t, size_t); | |
2230 | void (*free_func_ptr)(void*, size_t); | |
2231 | const char* ps = mpq_get_str(0, 10, m_data); | |
2232 | std::string s = ps; | |
7c673cae FG |
2233 | mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr); |
2234 | (*free_func_ptr)((void*)ps, std::strlen(ps) + 1); | |
2235 | return s; | |
2236 | } | |
2237 | ~gmp_rational() | |
2238 | { | |
92f5a8d4 | 2239 | if (m_data[0]._mp_num._mp_d || m_data[0]._mp_den._mp_d) |
7c673cae FG |
2240 | mpq_clear(m_data); |
2241 | } | |
2242 | void negate() | |
2243 | { | |
2244 | BOOST_ASSERT(m_data[0]._mp_num._mp_d); | |
2245 | mpq_neg(m_data, m_data); | |
2246 | } | |
92f5a8d4 | 2247 | int compare(const gmp_rational& o) const |
7c673cae FG |
2248 | { |
2249 | BOOST_ASSERT(m_data[0]._mp_num._mp_d && o.m_data[0]._mp_num._mp_d); | |
2250 | return mpq_cmp(m_data, o.m_data); | |
2251 | } | |
2252 | template <class V> | |
92f5a8d4 | 2253 | int compare(V v) const |
7c673cae FG |
2254 | { |
2255 | gmp_rational d; | |
2256 | d = v; | |
2257 | return compare(d); | |
2258 | } | |
92f5a8d4 | 2259 | int compare(unsigned long v) const |
7c673cae FG |
2260 | { |
2261 | BOOST_ASSERT(m_data[0]._mp_num._mp_d); | |
2262 | return mpq_cmp_ui(m_data, v, 1); | |
2263 | } | |
92f5a8d4 | 2264 | int compare(long v) const |
7c673cae FG |
2265 | { |
2266 | BOOST_ASSERT(m_data[0]._mp_num._mp_d); | |
2267 | return mpq_cmp_si(m_data, v, 1); | |
2268 | } | |
2269 | mpq_t& data() | |
2270 | { | |
2271 | BOOST_ASSERT(m_data[0]._mp_num._mp_d); | |
2272 | return m_data; | |
2273 | } | |
92f5a8d4 | 2274 | const mpq_t& data() const |
7c673cae FG |
2275 | { |
2276 | BOOST_ASSERT(m_data[0]._mp_num._mp_d); | |
2277 | return m_data; | |
2278 | } | |
92f5a8d4 TL |
2279 | |
2280 | protected: | |
7c673cae FG |
2281 | mpq_t m_data; |
2282 | }; | |
2283 | ||
2284 | inline bool eval_is_zero(const gmp_rational& val) | |
2285 | { | |
2286 | return mpq_sgn(val.data()) == 0; | |
2287 | } | |
2288 | template <class T> | |
2289 | inline bool eval_eq(gmp_rational& a, const T& b) | |
2290 | { | |
2291 | return a.compare(b) == 0; | |
2292 | } | |
2293 | template <class T> | |
2294 | inline bool eval_lt(gmp_rational& a, const T& b) | |
2295 | { | |
2296 | return a.compare(b) < 0; | |
2297 | } | |
2298 | template <class T> | |
2299 | inline bool eval_gt(gmp_rational& a, const T& b) | |
2300 | { | |
2301 | return a.compare(b) > 0; | |
2302 | } | |
2303 | ||
2304 | inline void eval_add(gmp_rational& t, const gmp_rational& o) | |
2305 | { | |
2306 | mpq_add(t.data(), t.data(), o.data()); | |
2307 | } | |
2308 | inline void eval_subtract(gmp_rational& t, const gmp_rational& o) | |
2309 | { | |
2310 | mpq_sub(t.data(), t.data(), o.data()); | |
2311 | } | |
2312 | inline void eval_multiply(gmp_rational& t, const gmp_rational& o) | |
2313 | { | |
2314 | mpq_mul(t.data(), t.data(), o.data()); | |
2315 | } | |
2316 | inline void eval_divide(gmp_rational& t, const gmp_rational& o) | |
2317 | { | |
92f5a8d4 | 2318 | if (eval_is_zero(o)) |
7c673cae FG |
2319 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
2320 | mpq_div(t.data(), t.data(), o.data()); | |
2321 | } | |
2322 | inline void eval_add(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) | |
2323 | { | |
2324 | mpq_add(t.data(), p.data(), o.data()); | |
2325 | } | |
2326 | inline void eval_subtract(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) | |
2327 | { | |
2328 | mpq_sub(t.data(), p.data(), o.data()); | |
2329 | } | |
2330 | inline void eval_multiply(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) | |
2331 | { | |
2332 | mpq_mul(t.data(), p.data(), o.data()); | |
2333 | } | |
2334 | inline void eval_divide(gmp_rational& t, const gmp_rational& p, const gmp_rational& o) | |
2335 | { | |
92f5a8d4 | 2336 | if (eval_is_zero(o)) |
7c673cae FG |
2337 | BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero.")); |
2338 | mpq_div(t.data(), p.data(), o.data()); | |
2339 | } | |
2340 | ||
2341 | inline int eval_get_sign(const gmp_rational& val) | |
2342 | { | |
2343 | return mpq_sgn(val.data()); | |
2344 | } | |
f67539c2 TL |
2345 | template <class R> |
2346 | inline typename enable_if_c<number_category<R>::value == number_kind_floating_point>::type eval_convert_to(R* result, const gmp_rational& backend) | |
7c673cae | 2347 | { |
f67539c2 TL |
2348 | // |
2349 | // The generic conversion is as good as anything we can write here: | |
7c673cae FG |
2350 | // |
2351 | // This does not round correctly: | |
2352 | // | |
2353 | //*result = mpq_get_d(val.data()); | |
2354 | // | |
2355 | // This does: | |
2356 | // | |
f67539c2 | 2357 | ::boost::multiprecision::detail::generic_convert_rational_to_float(*result, backend); |
7c673cae | 2358 | } |
f67539c2 TL |
2359 | #ifdef BOOST_HAS_FLOAT128 |
2360 | inline void eval_convert_to(__float128* result, const gmp_rational& val) | |
2361 | { | |
2362 | using default_ops::eval_convert_to; | |
2363 | ||
2364 | gmp_int n, d; | |
2365 | __float128 fn, fd; | |
2366 | mpz_set(n.data(), mpq_numref(val.data())); | |
2367 | mpz_set(d.data(), mpq_denref(val.data())); | |
2368 | ||
2369 | eval_convert_to(&fn, n); | |
2370 | eval_convert_to(&fd, d); | |
2371 | ||
2372 | *result = fn / fd; | |
2373 | } | |
2374 | #endif | |
7c673cae FG |
2375 | |
2376 | inline void eval_convert_to(long* result, const gmp_rational& val) | |
2377 | { | |
2378 | double r; | |
2379 | eval_convert_to(&r, val); | |
2380 | *result = static_cast<long>(r); | |
2381 | } | |
2382 | ||
2383 | inline void eval_convert_to(unsigned long* result, const gmp_rational& val) | |
2384 | { | |
2385 | double r; | |
2386 | eval_convert_to(&r, val); | |
2387 | *result = static_cast<long>(r); | |
2388 | } | |
2389 | ||
2390 | inline void eval_abs(gmp_rational& result, const gmp_rational& val) | |
2391 | { | |
2392 | mpq_abs(result.data(), val.data()); | |
2393 | } | |
2394 | ||
2395 | inline void assign_components(gmp_rational& result, unsigned long v1, unsigned long v2) | |
2396 | { | |
2397 | mpq_set_ui(result.data(), v1, v2); | |
2398 | mpq_canonicalize(result.data()); | |
2399 | } | |
2400 | inline void assign_components(gmp_rational& result, long v1, long v2) | |
2401 | { | |
2402 | mpq_set_si(result.data(), v1, v2); | |
2403 | mpq_canonicalize(result.data()); | |
2404 | } | |
2405 | inline void assign_components(gmp_rational& result, gmp_int const& v1, gmp_int const& v2) | |
2406 | { | |
2407 | mpz_set(mpq_numref(result.data()), v1.data()); | |
2408 | mpz_set(mpq_denref(result.data()), v2.data()); | |
2409 | mpq_canonicalize(result.data()); | |
2410 | } | |
2411 | ||
2412 | inline std::size_t hash_value(const gmp_rational& val) | |
2413 | { | |
2414 | std::size_t result = 0; | |
92f5a8d4 | 2415 | for (int i = 0; i < std::abs(val.data()[0]._mp_num._mp_size); ++i) |
7c673cae | 2416 | boost::hash_combine(result, val.data()[0]._mp_num._mp_d[i]); |
92f5a8d4 | 2417 | for (int i = 0; i < std::abs(val.data()[0]._mp_den._mp_size); ++i) |
7c673cae FG |
2418 | boost::hash_combine(result, val.data()[0]._mp_den._mp_d[i]); |
2419 | boost::hash_combine(result, val.data()[0]._mp_num._mp_size); | |
2420 | return result; | |
2421 | } | |
2422 | ||
2423 | // | |
2424 | // Some member functions that are dependent upon previous code go here: | |
2425 | // | |
2426 | template <unsigned Digits10> | |
2427 | template <unsigned D> | |
2428 | inline gmp_float<Digits10>::gmp_float(const gmp_float<D>& o, typename enable_if_c<D <= Digits10>::type*) | |
2429 | { | |
f67539c2 | 2430 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision())); |
7c673cae FG |
2431 | mpf_set(this->m_data, o.data()); |
2432 | } | |
2433 | template <unsigned Digits10> | |
2434 | template <unsigned D> | |
2435 | inline gmp_float<Digits10>::gmp_float(const gmp_float<D>& o, typename disable_if_c<D <= Digits10>::type*) | |
2436 | { | |
f67539c2 | 2437 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision())); |
7c673cae FG |
2438 | mpf_set(this->m_data, o.data()); |
2439 | } | |
2440 | template <unsigned Digits10> | |
2441 | inline gmp_float<Digits10>::gmp_float(const gmp_int& o) | |
2442 | { | |
f67539c2 | 2443 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision())); |
7c673cae FG |
2444 | mpf_set_z(this->data(), o.data()); |
2445 | } | |
2446 | template <unsigned Digits10> | |
2447 | inline gmp_float<Digits10>::gmp_float(const gmp_rational& o) | |
2448 | { | |
f67539c2 | 2449 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision())); |
7c673cae FG |
2450 | mpf_set_q(this->data(), o.data()); |
2451 | } | |
2452 | template <unsigned Digits10> | |
2453 | template <unsigned D> | |
2454 | inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_float<D>& o) | |
2455 | { | |
92f5a8d4 | 2456 | if (this->m_data[0]._mp_d == 0) |
f67539c2 | 2457 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision())); |
7c673cae FG |
2458 | mpf_set(this->m_data, o.data()); |
2459 | return *this; | |
2460 | } | |
2461 | template <unsigned Digits10> | |
2462 | inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_int& o) | |
2463 | { | |
92f5a8d4 | 2464 | if (this->m_data[0]._mp_d == 0) |
f67539c2 | 2465 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision())); |
7c673cae FG |
2466 | mpf_set_z(this->data(), o.data()); |
2467 | return *this; | |
2468 | } | |
2469 | template <unsigned Digits10> | |
2470 | inline gmp_float<Digits10>& gmp_float<Digits10>::operator=(const gmp_rational& o) | |
2471 | { | |
92f5a8d4 | 2472 | if (this->m_data[0]._mp_d == 0) |
f67539c2 | 2473 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(Digits10 ? Digits10 : (unsigned)this->get_default_precision())); |
7c673cae FG |
2474 | mpf_set_q(this->data(), o.data()); |
2475 | return *this; | |
2476 | } | |
f67539c2 | 2477 | inline gmp_float<0>::gmp_float(const gmp_int& o) : requested_precision(get_default_precision()) |
7c673cae | 2478 | { |
f67539c2 | 2479 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); |
7c673cae FG |
2480 | mpf_set_z(this->data(), o.data()); |
2481 | } | |
f67539c2 | 2482 | inline gmp_float<0>::gmp_float(const gmp_rational& o) : requested_precision(get_default_precision()) |
7c673cae | 2483 | { |
f67539c2 | 2484 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); |
7c673cae FG |
2485 | mpf_set_q(this->data(), o.data()); |
2486 | } | |
2487 | inline gmp_float<0>& gmp_float<0>::operator=(const gmp_int& o) | |
2488 | { | |
92f5a8d4 | 2489 | if (this->m_data[0]._mp_d == 0) |
f67539c2 TL |
2490 | { |
2491 | requested_precision = this->get_default_precision(); | |
2492 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); | |
2493 | } | |
7c673cae FG |
2494 | mpf_set_z(this->data(), o.data()); |
2495 | return *this; | |
2496 | } | |
2497 | inline gmp_float<0>& gmp_float<0>::operator=(const gmp_rational& o) | |
2498 | { | |
92f5a8d4 | 2499 | if (this->m_data[0]._mp_d == 0) |
f67539c2 TL |
2500 | { |
2501 | requested_precision = this->get_default_precision(); | |
2502 | mpf_init2(this->m_data, multiprecision::detail::digits10_2_2(requested_precision)); | |
2503 | } | |
7c673cae FG |
2504 | mpf_set_q(this->data(), o.data()); |
2505 | return *this; | |
2506 | } | |
2507 | inline gmp_int::gmp_int(const gmp_rational& o) | |
2508 | { | |
2509 | mpz_init(this->m_data); | |
2510 | mpz_set_q(this->m_data, o.data()); | |
2511 | } | |
2512 | inline gmp_int& gmp_int::operator=(const gmp_rational& o) | |
2513 | { | |
92f5a8d4 | 2514 | if (this->m_data[0]._mp_d == 0) |
7c673cae FG |
2515 | mpz_init(this->m_data); |
2516 | mpz_set_q(this->m_data, o.data()); | |
2517 | return *this; | |
2518 | } | |
2519 | ||
2520 | } //namespace backends | |
2521 | ||
92f5a8d4 | 2522 | using boost::multiprecision::backends::gmp_float; |
7c673cae FG |
2523 | using boost::multiprecision::backends::gmp_int; |
2524 | using boost::multiprecision::backends::gmp_rational; | |
7c673cae | 2525 | |
92f5a8d4 TL |
2526 | template <expression_template_option ExpressionTemplates> |
2527 | struct component_type<number<gmp_rational, ExpressionTemplates> > | |
7c673cae | 2528 | { |
92f5a8d4 | 2529 | typedef number<gmp_int, ExpressionTemplates> type; |
7c673cae FG |
2530 | }; |
2531 | ||
2532 | template <expression_template_option ET> | |
2533 | inline number<gmp_int, ET> numerator(const number<gmp_rational, ET>& val) | |
2534 | { | |
2535 | number<gmp_int, ET> result; | |
2536 | mpz_set(result.backend().data(), (mpq_numref(val.backend().data()))); | |
2537 | return result; | |
2538 | } | |
2539 | template <expression_template_option ET> | |
2540 | inline number<gmp_int, ET> denominator(const number<gmp_rational, ET>& val) | |
2541 | { | |
2542 | number<gmp_int, ET> result; | |
2543 | mpz_set(result.backend().data(), (mpq_denref(val.backend().data()))); | |
2544 | return result; | |
2545 | } | |
2546 | ||
92f5a8d4 | 2547 | namespace detail { |
7c673cae FG |
2548 | |
2549 | #ifdef BOOST_NO_SFINAE_EXPR | |
2550 | ||
92f5a8d4 TL |
2551 | template <> |
2552 | struct is_explicitly_convertible<canonical<mpf_t, gmp_int>::type, gmp_int> : public mpl::true_ | |
2553 | {}; | |
2554 | template <> | |
2555 | struct is_explicitly_convertible<canonical<mpq_t, gmp_int>::type, gmp_int> : public mpl::true_ | |
2556 | {}; | |
2557 | template <unsigned Digits10> | |
2558 | struct is_explicitly_convertible<gmp_float<Digits10>, gmp_int> : public mpl::true_ | |
2559 | {}; | |
2560 | template <> | |
2561 | struct is_explicitly_convertible<gmp_rational, gmp_int> : public mpl::true_ | |
2562 | {}; | |
2563 | template <unsigned D1, unsigned D2> | |
2564 | struct is_explicitly_convertible<gmp_float<D1>, gmp_float<D2> > : public mpl::true_ | |
2565 | {}; | |
7c673cae FG |
2566 | |
2567 | #endif | |
2568 | ||
2569 | template <> | |
2570 | struct digits2<number<gmp_float<0>, et_on> > | |
2571 | { | |
2572 | static long value() | |
2573 | { | |
92f5a8d4 | 2574 | return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision()); |
7c673cae FG |
2575 | } |
2576 | }; | |
2577 | ||
2578 | template <> | |
2579 | struct digits2<number<gmp_float<0>, et_off> > | |
2580 | { | |
2581 | static long value() | |
2582 | { | |
92f5a8d4 | 2583 | return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision()); |
7c673cae FG |
2584 | } |
2585 | }; | |
2586 | ||
2587 | template <> | |
2588 | struct digits2<number<debug_adaptor<gmp_float<0> >, et_on> > | |
2589 | { | |
2590 | static long value() | |
2591 | { | |
92f5a8d4 | 2592 | return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision()); |
7c673cae FG |
2593 | } |
2594 | }; | |
2595 | ||
2596 | template <> | |
2597 | struct digits2<number<debug_adaptor<gmp_float<0> >, et_off> > | |
2598 | { | |
2599 | static long value() | |
2600 | { | |
92f5a8d4 | 2601 | return multiprecision::detail::digits10_2_2(gmp_float<0>::default_precision()); |
7c673cae FG |
2602 | } |
2603 | }; | |
2604 | ||
20effc67 TL |
2605 | template <unsigned Digits10> |
2606 | struct transcendental_reduction_type<boost::multiprecision::backends::gmp_float<Digits10> > | |
2607 | { | |
2608 | // | |
2609 | // The type used for trigonometric reduction needs 3 times the precision of the base type. | |
2610 | // This is double the precision of the original type, plus the largest exponent supported. | |
2611 | // As a practical measure the largest argument supported is 1/eps, as supporting larger | |
2612 | // arguments requires the division of argument by PI/2 to also be done at higher precision, | |
2613 | // otherwise the result (an integer) can not be represented exactly. | |
2614 | // | |
2615 | // See ARGUMENT REDUCTION FOR HUGE ARGUMENTS. K C Ng. | |
2616 | // | |
2617 | typedef boost::multiprecision::backends::gmp_float<Digits10 * 3> type; | |
2618 | }; | |
2619 | ||
2620 | ||
92f5a8d4 | 2621 | } // namespace detail |
7c673cae | 2622 | |
92f5a8d4 TL |
2623 | template <> |
2624 | struct number_category<detail::canonical<mpz_t, gmp_int>::type> : public mpl::int_<number_kind_integer> | |
2625 | {}; | |
2626 | template <> | |
2627 | struct number_category<detail::canonical<mpq_t, gmp_rational>::type> : public mpl::int_<number_kind_rational> | |
2628 | {}; | |
2629 | template <> | |
2630 | struct number_category<detail::canonical<mpf_t, gmp_float<0> >::type> : public mpl::int_<number_kind_floating_point> | |
2631 | {}; | |
7c673cae | 2632 | |
92f5a8d4 TL |
2633 | namespace detail { |
2634 | template <> | |
2635 | struct is_variable_precision<backends::gmp_float<0> > : public true_type | |
2636 | {}; | |
2637 | } // namespace detail | |
7c673cae | 2638 | |
92f5a8d4 TL |
2639 | typedef number<gmp_float<50> > mpf_float_50; |
2640 | typedef number<gmp_float<100> > mpf_float_100; | |
2641 | typedef number<gmp_float<500> > mpf_float_500; | |
2642 | typedef number<gmp_float<1000> > mpf_float_1000; | |
2643 | typedef number<gmp_float<0> > mpf_float; | |
2644 | typedef number<gmp_int> mpz_int; | |
2645 | typedef number<gmp_rational> mpq_rational; | |
7c673cae | 2646 | |
92f5a8d4 | 2647 | } // namespace multiprecision |
7c673cae | 2648 | |
92f5a8d4 | 2649 | namespace math { namespace tools { |
7c673cae | 2650 | |
20effc67 TL |
2651 | inline void set_output_precision(const boost::multiprecision::mpf_float& val, std::ostream& os) |
2652 | { | |
2653 | os << std::setprecision(val.precision()); | |
2654 | } | |
2655 | ||
92f5a8d4 TL |
2656 | template <> |
2657 | inline int digits<boost::multiprecision::mpf_float>() | |
7c673cae | 2658 | #ifdef BOOST_MATH_NOEXCEPT |
92f5a8d4 | 2659 | BOOST_NOEXCEPT |
7c673cae | 2660 | #endif |
92f5a8d4 TL |
2661 | { |
2662 | return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::default_precision()); | |
2663 | } | |
2664 | template <> | |
2665 | inline int digits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >() | |
7c673cae | 2666 | #ifdef BOOST_MATH_NOEXCEPT |
92f5a8d4 | 2667 | BOOST_NOEXCEPT |
7c673cae | 2668 | #endif |
92f5a8d4 TL |
2669 | { |
2670 | return multiprecision::detail::digits10_2_2(boost::multiprecision::mpf_float::default_precision()); | |
2671 | } | |
7c673cae | 2672 | |
92f5a8d4 TL |
2673 | template <> |
2674 | inline boost::multiprecision::mpf_float | |
2675 | max_value<boost::multiprecision::mpf_float>() | |
2676 | { | |
2677 | boost::multiprecision::mpf_float result(0.5); | |
2678 | mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1); | |
2679 | return result; | |
2680 | } | |
7c673cae | 2681 | |
92f5a8d4 TL |
2682 | template <> |
2683 | inline boost::multiprecision::mpf_float | |
2684 | min_value<boost::multiprecision::mpf_float>() | |
2685 | { | |
2686 | boost::multiprecision::mpf_float result(0.5); | |
20effc67 | 2687 | mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1); |
92f5a8d4 TL |
2688 | return result; |
2689 | } | |
7c673cae | 2690 | |
92f5a8d4 TL |
2691 | template <> |
2692 | inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> | |
2693 | max_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >() | |
2694 | { | |
2695 | boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5); | |
2696 | mpf_mul_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1); | |
2697 | return result; | |
2698 | } | |
7c673cae | 2699 | |
92f5a8d4 TL |
2700 | template <> |
2701 | inline boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> | |
2702 | min_value<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> >() | |
2703 | { | |
2704 | boost::multiprecision::number<boost::multiprecision::gmp_float<0>, boost::multiprecision::et_off> result(0.5); | |
2705 | mpf_div_2exp(result.backend().data(), result.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1); | |
2706 | return result; | |
2707 | } | |
7c673cae | 2708 | |
92f5a8d4 TL |
2709 | template <> |
2710 | inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >() | |
7c673cae | 2711 | #ifdef BOOST_MATH_NOEXCEPT |
92f5a8d4 | 2712 | BOOST_NOEXCEPT |
7c673cae | 2713 | #endif |
92f5a8d4 TL |
2714 | { |
2715 | return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::default_precision()); | |
2716 | } | |
2717 | template <> | |
2718 | inline int digits<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >() | |
7c673cae | 2719 | #ifdef BOOST_MATH_NOEXCEPT |
92f5a8d4 | 2720 | BOOST_NOEXCEPT |
7c673cae | 2721 | #endif |
92f5a8d4 TL |
2722 | { |
2723 | return multiprecision::detail::digits10_2_2(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> >::default_precision()); | |
2724 | } | |
7c673cae | 2725 | |
92f5a8d4 TL |
2726 | template <> |
2727 | inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > | |
2728 | max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >() | |
2729 | { | |
2730 | return max_value<boost::multiprecision::mpf_float>().backend(); | |
2731 | } | |
7c673cae | 2732 | |
92f5a8d4 TL |
2733 | template <> |
2734 | inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > | |
2735 | min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::mpf_float::backend_type> > >() | |
2736 | { | |
2737 | return min_value<boost::multiprecision::mpf_float>().backend(); | |
2738 | } | |
7c673cae | 2739 | |
92f5a8d4 TL |
2740 | template <> |
2741 | inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> | |
2742 | max_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >() | |
2743 | { | |
2744 | return max_value<boost::multiprecision::mpf_float>().backend(); | |
2745 | } | |
7c673cae | 2746 | |
92f5a8d4 TL |
2747 | template <> |
2748 | inline boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> | |
2749 | min_value<boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::gmp_float<0> >, boost::multiprecision::et_off> >() | |
2750 | { | |
2751 | return min_value<boost::multiprecision::mpf_float>().backend(); | |
2752 | } | |
7c673cae | 2753 | |
92f5a8d4 | 2754 | }} // namespace math::tools |
7c673cae | 2755 | |
92f5a8d4 | 2756 | } // namespace boost |
7c673cae | 2757 | |
92f5a8d4 | 2758 | namespace std { |
7c673cae FG |
2759 | |
2760 | // | |
2761 | // numeric_limits [partial] specializations for the types declared in this header: | |
2762 | // | |
92f5a8d4 | 2763 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> |
7c673cae FG |
2764 | class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> > |
2765 | { | |
2766 | typedef boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> number_type; | |
92f5a8d4 TL |
2767 | |
2768 | public: | |
7c673cae FG |
2769 | BOOST_STATIC_CONSTEXPR bool is_specialized = true; |
2770 | // | |
2771 | // min and max values chosen so as to not cause segfaults when calling | |
2772 | // mpf_get_str on 64-bit Linux builds. Possibly we could use larger | |
2773 | // exponent values elsewhere. | |
2774 | // | |
92f5a8d4 | 2775 | static number_type(min)() |
7c673cae FG |
2776 | { |
2777 | initializer.do_nothing(); | |
2778 | static std::pair<bool, number_type> value; | |
92f5a8d4 | 2779 | if (!value.first) |
7c673cae | 2780 | { |
92f5a8d4 | 2781 | value.first = true; |
7c673cae FG |
2782 | value.second = 1; |
2783 | mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1); | |
2784 | } | |
2785 | return value.second; | |
2786 | } | |
92f5a8d4 | 2787 | static number_type(max)() |
7c673cae FG |
2788 | { |
2789 | initializer.do_nothing(); | |
2790 | static std::pair<bool, number_type> value; | |
92f5a8d4 | 2791 | if (!value.first) |
7c673cae | 2792 | { |
92f5a8d4 | 2793 | value.first = true; |
7c673cae FG |
2794 | value.second = 1; |
2795 | mpf_mul_2exp(value.second.backend().data(), value.second.backend().data(), (std::numeric_limits<mp_exp_t>::max)() / 64 + 1); | |
2796 | } | |
2797 | return value.second; | |
2798 | } | |
2799 | BOOST_STATIC_CONSTEXPR number_type lowest() | |
2800 | { | |
2801 | return -(max)(); | |
2802 | } | |
92f5a8d4 | 2803 | BOOST_STATIC_CONSTEXPR int digits = static_cast<int>((Digits10 * 1000L) / 301L + ((Digits10 * 1000L) % 301L ? 2 : 1)); |
7c673cae FG |
2804 | BOOST_STATIC_CONSTEXPR int digits10 = Digits10; |
2805 | // Have to allow for a possible extra limb inside the gmp data structure: | |
92f5a8d4 TL |
2806 | BOOST_STATIC_CONSTEXPR int max_digits10 = Digits10 + 3 + ((GMP_LIMB_BITS * 301L) / 1000L); |
2807 | BOOST_STATIC_CONSTEXPR bool is_signed = true; | |
2808 | BOOST_STATIC_CONSTEXPR bool is_integer = false; | |
2809 | BOOST_STATIC_CONSTEXPR bool is_exact = false; | |
2810 | BOOST_STATIC_CONSTEXPR int radix = 2; | |
2811 | static number_type epsilon() | |
7c673cae FG |
2812 | { |
2813 | initializer.do_nothing(); | |
2814 | static std::pair<bool, number_type> value; | |
92f5a8d4 | 2815 | if (!value.first) |
7c673cae | 2816 | { |
92f5a8d4 | 2817 | value.first = true; |
7c673cae FG |
2818 | value.second = 1; |
2819 | mpf_div_2exp(value.second.backend().data(), value.second.backend().data(), std::numeric_limits<number_type>::digits - 1); | |
2820 | } | |
2821 | return value.second; | |
2822 | } | |
2823 | // What value should this be???? | |
2824 | static number_type round_error() | |
2825 | { | |
2826 | // returns epsilon/2 | |
2827 | initializer.do_nothing(); | |
2828 | static std::pair<bool, number_type> value; | |
92f5a8d4 | 2829 | if (!value.first) |
7c673cae | 2830 | { |
92f5a8d4 | 2831 | value.first = true; |
7c673cae FG |
2832 | value.second = 1; |
2833 | } | |
2834 | return value.second; | |
2835 | } | |
f67539c2 TL |
2836 | BOOST_STATIC_CONSTEXPR long min_exponent = LONG_MIN; |
2837 | BOOST_STATIC_CONSTEXPR long min_exponent10 = (LONG_MIN / 1000) * 301L; | |
2838 | BOOST_STATIC_CONSTEXPR long max_exponent = LONG_MAX; | |
2839 | BOOST_STATIC_CONSTEXPR long max_exponent10 = (LONG_MAX / 1000) * 301L; | |
2840 | BOOST_STATIC_CONSTEXPR bool has_infinity = false; | |
2841 | BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; | |
2842 | BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; | |
2843 | BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; | |
2844 | BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; | |
2845 | BOOST_STATIC_CONSTEXPR number_type infinity() { return number_type(); } | |
2846 | BOOST_STATIC_CONSTEXPR number_type quiet_NaN() { return number_type(); } | |
2847 | BOOST_STATIC_CONSTEXPR number_type signaling_NaN() { return number_type(); } | |
2848 | BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(); } | |
2849 | BOOST_STATIC_CONSTEXPR bool is_iec559 = false; | |
2850 | BOOST_STATIC_CONSTEXPR bool is_bounded = true; | |
2851 | BOOST_STATIC_CONSTEXPR bool is_modulo = false; | |
2852 | BOOST_STATIC_CONSTEXPR bool traps = true; | |
2853 | BOOST_STATIC_CONSTEXPR bool tinyness_before = false; | |
2854 | BOOST_STATIC_CONSTEXPR float_round_style round_style = round_indeterminate; | |
7c673cae | 2855 | |
92f5a8d4 | 2856 | private: |
7c673cae FG |
2857 | struct data_initializer |
2858 | { | |
2859 | data_initializer() | |
2860 | { | |
2861 | std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::epsilon(); | |
2862 | std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::round_error(); | |
2863 | (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::min)(); | |
2864 | (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<digits10> > >::max)(); | |
2865 | } | |
92f5a8d4 | 2866 | void do_nothing() const {} |
7c673cae FG |
2867 | }; |
2868 | static const data_initializer initializer; | |
2869 | }; | |
2870 | ||
92f5a8d4 | 2871 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> |
7c673cae FG |
2872 | const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::initializer; |
2873 | ||
2874 | #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | |
2875 | ||
2876 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2877 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::digits; | |
2878 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2879 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::digits10; | |
2880 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2881 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_digits10; | |
2882 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2883 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_signed; | |
2884 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2885 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_integer; | |
2886 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2887 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_exact; | |
2888 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2889 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::radix; | |
2890 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2891 | BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::min_exponent; | |
2892 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2893 | BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::min_exponent10; | |
2894 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2895 | BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_exponent; | |
2896 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2897 | BOOST_CONSTEXPR_OR_CONST long numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::max_exponent10; | |
2898 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2899 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_infinity; | |
2900 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2901 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_quiet_NaN; | |
2902 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2903 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_signaling_NaN; | |
2904 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2905 | BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_denorm; | |
2906 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2907 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::has_denorm_loss; | |
2908 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2909 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_iec559; | |
2910 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2911 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_bounded; | |
2912 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2913 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::is_modulo; | |
2914 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2915 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::traps; | |
2916 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2917 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::tinyness_before; | |
2918 | template <unsigned Digits10, boost::multiprecision::expression_template_option ExpressionTemplates> | |
2919 | BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<Digits10>, ExpressionTemplates> >::round_style; | |
2920 | ||
2921 | #endif | |
2922 | ||
92f5a8d4 | 2923 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
7c673cae FG |
2924 | class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> > |
2925 | { | |
2926 | typedef boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> number_type; | |
92f5a8d4 TL |
2927 | |
2928 | public: | |
7c673cae | 2929 | BOOST_STATIC_CONSTEXPR bool is_specialized = false; |
92f5a8d4 TL |
2930 | static number_type(min)() { return number_type(); } |
2931 | static number_type(max)() { return number_type(); } | |
f67539c2 TL |
2932 | static number_type lowest() { return number_type(); } |
2933 | BOOST_STATIC_CONSTEXPR int digits = 0; | |
2934 | BOOST_STATIC_CONSTEXPR int digits10 = 0; | |
2935 | BOOST_STATIC_CONSTEXPR int max_digits10 = 0; | |
2936 | BOOST_STATIC_CONSTEXPR bool is_signed = false; | |
2937 | BOOST_STATIC_CONSTEXPR bool is_integer = false; | |
2938 | BOOST_STATIC_CONSTEXPR bool is_exact = false; | |
2939 | BOOST_STATIC_CONSTEXPR int radix = 0; | |
2940 | static number_type epsilon() { return number_type(); } | |
2941 | static number_type round_error() { return number_type(); } | |
2942 | BOOST_STATIC_CONSTEXPR int min_exponent = 0; | |
2943 | BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; | |
2944 | BOOST_STATIC_CONSTEXPR int max_exponent = 0; | |
2945 | BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; | |
2946 | BOOST_STATIC_CONSTEXPR bool has_infinity = false; | |
2947 | BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; | |
2948 | BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; | |
2949 | BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; | |
2950 | BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; | |
92f5a8d4 TL |
2951 | static number_type infinity() { return number_type(); } |
2952 | static number_type quiet_NaN() { return number_type(); } | |
2953 | static number_type signaling_NaN() { return number_type(); } | |
2954 | static number_type denorm_min() { return number_type(); } | |
2955 | BOOST_STATIC_CONSTEXPR bool is_iec559 = false; | |
2956 | BOOST_STATIC_CONSTEXPR bool is_bounded = false; | |
2957 | BOOST_STATIC_CONSTEXPR bool is_modulo = false; | |
2958 | BOOST_STATIC_CONSTEXPR bool traps = false; | |
2959 | BOOST_STATIC_CONSTEXPR bool tinyness_before = false; | |
f67539c2 | 2960 | BOOST_STATIC_CONSTEXPR float_round_style round_style = round_indeterminate; |
7c673cae FG |
2961 | }; |
2962 | ||
2963 | #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | |
2964 | ||
2965 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2966 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits; | |
2967 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2968 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::digits10; | |
2969 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2970 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_digits10; | |
2971 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2972 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_signed; | |
2973 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2974 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_integer; | |
2975 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2976 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_exact; | |
2977 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2978 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::radix; | |
2979 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2980 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent; | |
2981 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2982 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::min_exponent10; | |
2983 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2984 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent; | |
2985 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2986 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::max_exponent10; | |
2987 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2988 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_infinity; | |
2989 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2990 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_quiet_NaN; | |
2991 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2992 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_signaling_NaN; | |
2993 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2994 | BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm; | |
2995 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2996 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::has_denorm_loss; | |
2997 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
2998 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_iec559; | |
2999 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3000 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_bounded; | |
3001 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3002 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::is_modulo; | |
3003 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3004 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::traps; | |
3005 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3006 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::tinyness_before; | |
3007 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3008 | BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_float<0>, ExpressionTemplates> >::round_style; | |
3009 | ||
3010 | #endif | |
3011 | ||
92f5a8d4 | 3012 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
7c673cae FG |
3013 | class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> > |
3014 | { | |
3015 | typedef boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> number_type; | |
92f5a8d4 TL |
3016 | |
3017 | public: | |
7c673cae FG |
3018 | BOOST_STATIC_CONSTEXPR bool is_specialized = true; |
3019 | // | |
3020 | // Largest and smallest numbers are bounded only by available memory, set | |
3021 | // to zero: | |
3022 | // | |
92f5a8d4 | 3023 | static number_type(min)() |
7c673cae FG |
3024 | { |
3025 | return number_type(); | |
3026 | } | |
92f5a8d4 | 3027 | static number_type(max)() |
7c673cae FG |
3028 | { |
3029 | return number_type(); | |
3030 | } | |
f67539c2 TL |
3031 | static number_type lowest() { return (min)(); } |
3032 | BOOST_STATIC_CONSTEXPR int digits = INT_MAX; | |
3033 | BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; | |
3034 | BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 3; | |
3035 | BOOST_STATIC_CONSTEXPR bool is_signed = true; | |
3036 | BOOST_STATIC_CONSTEXPR bool is_integer = true; | |
3037 | BOOST_STATIC_CONSTEXPR bool is_exact = true; | |
3038 | BOOST_STATIC_CONSTEXPR int radix = 2; | |
3039 | static number_type epsilon() { return number_type(); } | |
3040 | static number_type round_error() { return number_type(); } | |
3041 | BOOST_STATIC_CONSTEXPR int min_exponent = 0; | |
3042 | BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; | |
3043 | BOOST_STATIC_CONSTEXPR int max_exponent = 0; | |
3044 | BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; | |
3045 | BOOST_STATIC_CONSTEXPR bool has_infinity = false; | |
3046 | BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; | |
3047 | BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; | |
3048 | BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; | |
3049 | BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; | |
92f5a8d4 TL |
3050 | static number_type infinity() { return number_type(); } |
3051 | static number_type quiet_NaN() { return number_type(); } | |
3052 | static number_type signaling_NaN() { return number_type(); } | |
3053 | static number_type denorm_min() { return number_type(); } | |
3054 | BOOST_STATIC_CONSTEXPR bool is_iec559 = false; | |
3055 | BOOST_STATIC_CONSTEXPR bool is_bounded = false; | |
3056 | BOOST_STATIC_CONSTEXPR bool is_modulo = false; | |
3057 | BOOST_STATIC_CONSTEXPR bool traps = false; | |
3058 | BOOST_STATIC_CONSTEXPR bool tinyness_before = false; | |
f67539c2 | 3059 | BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; |
7c673cae FG |
3060 | }; |
3061 | ||
3062 | #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | |
3063 | ||
3064 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3065 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits; | |
3066 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3067 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::digits10; | |
3068 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3069 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_digits10; | |
3070 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3071 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_signed; | |
3072 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3073 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_integer; | |
3074 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3075 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_exact; | |
3076 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3077 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::radix; | |
3078 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3079 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent; | |
3080 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3081 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::min_exponent10; | |
3082 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3083 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent; | |
3084 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3085 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::max_exponent10; | |
3086 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3087 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_infinity; | |
3088 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3089 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_quiet_NaN; | |
3090 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3091 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_signaling_NaN; | |
3092 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3093 | BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm; | |
3094 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3095 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::has_denorm_loss; | |
3096 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3097 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_iec559; | |
3098 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3099 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_bounded; | |
3100 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3101 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::is_modulo; | |
3102 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3103 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::traps; | |
3104 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3105 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::tinyness_before; | |
3106 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3107 | BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_int, ExpressionTemplates> >::round_style; | |
3108 | ||
3109 | #endif | |
3110 | ||
92f5a8d4 | 3111 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
7c673cae FG |
3112 | class numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> > |
3113 | { | |
3114 | typedef boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> number_type; | |
92f5a8d4 TL |
3115 | |
3116 | public: | |
7c673cae FG |
3117 | BOOST_STATIC_CONSTEXPR bool is_specialized = true; |
3118 | // | |
3119 | // Largest and smallest numbers are bounded only by available memory, set | |
3120 | // to zero: | |
3121 | // | |
92f5a8d4 | 3122 | static number_type(min)() |
7c673cae FG |
3123 | { |
3124 | return number_type(); | |
3125 | } | |
92f5a8d4 | 3126 | static number_type(max)() |
7c673cae FG |
3127 | { |
3128 | return number_type(); | |
3129 | } | |
3130 | static number_type lowest() { return (min)(); } | |
3131 | // Digits are unbounded, use zero for now: | |
f67539c2 TL |
3132 | BOOST_STATIC_CONSTEXPR int digits = INT_MAX; |
3133 | BOOST_STATIC_CONSTEXPR int digits10 = (INT_MAX / 1000) * 301L; | |
3134 | BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 3; | |
3135 | BOOST_STATIC_CONSTEXPR bool is_signed = true; | |
3136 | BOOST_STATIC_CONSTEXPR bool is_integer = false; | |
3137 | BOOST_STATIC_CONSTEXPR bool is_exact = true; | |
3138 | BOOST_STATIC_CONSTEXPR int radix = 2; | |
3139 | static number_type epsilon() { return number_type(); } | |
3140 | static number_type round_error() { return number_type(); } | |
3141 | BOOST_STATIC_CONSTEXPR int min_exponent = 0; | |
3142 | BOOST_STATIC_CONSTEXPR int min_exponent10 = 0; | |
3143 | BOOST_STATIC_CONSTEXPR int max_exponent = 0; | |
3144 | BOOST_STATIC_CONSTEXPR int max_exponent10 = 0; | |
3145 | BOOST_STATIC_CONSTEXPR bool has_infinity = false; | |
3146 | BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = false; | |
3147 | BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; | |
3148 | BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; | |
3149 | BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; | |
92f5a8d4 TL |
3150 | static number_type infinity() { return number_type(); } |
3151 | static number_type quiet_NaN() { return number_type(); } | |
3152 | static number_type signaling_NaN() { return number_type(); } | |
3153 | static number_type denorm_min() { return number_type(); } | |
3154 | BOOST_STATIC_CONSTEXPR bool is_iec559 = false; | |
3155 | BOOST_STATIC_CONSTEXPR bool is_bounded = false; | |
3156 | BOOST_STATIC_CONSTEXPR bool is_modulo = false; | |
3157 | BOOST_STATIC_CONSTEXPR bool traps = false; | |
3158 | BOOST_STATIC_CONSTEXPR bool tinyness_before = false; | |
f67539c2 | 3159 | BOOST_STATIC_CONSTEXPR float_round_style round_style = round_toward_zero; |
7c673cae FG |
3160 | }; |
3161 | ||
3162 | #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | |
3163 | ||
3164 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3165 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits; | |
3166 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3167 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::digits10; | |
3168 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3169 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_digits10; | |
3170 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3171 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_signed; | |
3172 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3173 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_integer; | |
3174 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3175 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_exact; | |
3176 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3177 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::radix; | |
3178 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3179 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent; | |
3180 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3181 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::min_exponent10; | |
3182 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3183 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent; | |
3184 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3185 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::max_exponent10; | |
3186 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3187 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_infinity; | |
3188 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3189 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_quiet_NaN; | |
3190 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3191 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_signaling_NaN; | |
3192 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3193 | BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm; | |
3194 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3195 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::has_denorm_loss; | |
3196 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3197 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_iec559; | |
3198 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3199 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_bounded; | |
3200 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3201 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::is_modulo; | |
3202 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3203 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::traps; | |
3204 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3205 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::tinyness_before; | |
3206 | template <boost::multiprecision::expression_template_option ExpressionTemplates> | |
3207 | BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::gmp_rational, ExpressionTemplates> >::round_style; | |
3208 | ||
3209 | #endif | |
3210 | ||
3211 | #ifdef BOOST_MSVC | |
3212 | #pragma warning(pop) | |
3213 | #endif | |
3214 | ||
3215 | } // namespace std | |
3216 | ||
3217 | #endif |