]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | /////////////////////////////////////////////////////////////////////////////// |
1e59de90 TL |
2 | // Copyright 2011 John Maddock. |
3 | // Copyright 2021 Matt Borland. Distributed under the Boost | |
7c673cae FG |
4 | // Software License, Version 1.0. (See accompanying file |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | ||
7 | #ifndef BOOST_MATH_MP_TOMMATH_BACKEND_HPP | |
8 | #define BOOST_MATH_MP_TOMMATH_BACKEND_HPP | |
9 | ||
1e59de90 TL |
10 | #include <boost/multiprecision/detail/standalone_config.hpp> |
11 | #include <boost/multiprecision/detail/fpclassify.hpp> | |
7c673cae FG |
12 | #include <boost/multiprecision/number.hpp> |
13 | #include <boost/multiprecision/rational_adaptor.hpp> | |
14 | #include <boost/multiprecision/detail/integer_ops.hpp> | |
1e59de90 TL |
15 | #include <boost/multiprecision/detail/hash.hpp> |
16 | #include <boost/multiprecision/detail/no_exceptions_support.hpp> | |
17 | #include <boost/multiprecision/detail/assert.hpp> | |
18 | #include <cstdint> | |
7c673cae | 19 | #include <tommath.h> |
92f5a8d4 | 20 | #include <cctype> |
7c673cae FG |
21 | #include <cmath> |
22 | #include <limits> | |
23 | #include <climits> | |
1e59de90 TL |
24 | #include <cstddef> |
25 | #include <cstdlib> | |
26 | #include <string> | |
7c673cae | 27 | |
f67539c2 TL |
28 | namespace boost { |
29 | namespace multiprecision { | |
92f5a8d4 | 30 | namespace backends { |
7c673cae | 31 | |
92f5a8d4 | 32 | namespace detail { |
7c673cae | 33 | |
f67539c2 TL |
34 | template <class ErrType> |
35 | inline void check_tommath_result(ErrType v) | |
7c673cae | 36 | { |
92f5a8d4 | 37 | if (v != MP_OKAY) |
7c673cae | 38 | { |
1e59de90 | 39 | BOOST_MP_THROW_EXCEPTION(std::runtime_error(mp_error_to_string(v))); |
7c673cae FG |
40 | } |
41 | } | |
42 | ||
92f5a8d4 | 43 | } // namespace detail |
7c673cae FG |
44 | |
45 | struct tommath_int; | |
46 | ||
47 | void eval_multiply(tommath_int& t, const tommath_int& o); | |
48 | void eval_add(tommath_int& t, const tommath_int& o); | |
49 | ||
50 | struct tommath_int | |
51 | { | |
1e59de90 TL |
52 | using signed_types = std::tuple<std::int32_t, long long> ; |
53 | using unsigned_types = std::tuple<std::uint32_t, unsigned long long>; | |
54 | using float_types = std::tuple<long double> ; | |
7c673cae FG |
55 | |
56 | tommath_int() | |
57 | { | |
58 | detail::check_tommath_result(mp_init(&m_data)); | |
59 | } | |
60 | tommath_int(const tommath_int& o) | |
61 | { | |
62 | detail::check_tommath_result(mp_init_copy(&m_data, const_cast< ::mp_int*>(&o.m_data))); | |
63 | } | |
1e59de90 TL |
64 | // rvalues: |
65 | tommath_int(tommath_int&& o) noexcept | |
7c673cae | 66 | { |
92f5a8d4 | 67 | m_data = o.m_data; |
7c673cae FG |
68 | o.m_data.dp = 0; |
69 | } | |
92f5a8d4 | 70 | tommath_int& operator=(tommath_int&& o) |
7c673cae FG |
71 | { |
72 | mp_exch(&m_data, &o.m_data); | |
73 | return *this; | |
74 | } | |
92f5a8d4 | 75 | tommath_int& operator=(const tommath_int& o) |
7c673cae | 76 | { |
92f5a8d4 | 77 | if (m_data.dp == 0) |
7c673cae | 78 | detail::check_tommath_result(mp_init(&m_data)); |
92f5a8d4 | 79 | if (o.m_data.dp) |
7c673cae FG |
80 | detail::check_tommath_result(mp_copy(const_cast< ::mp_int*>(&o.m_data), &m_data)); |
81 | return *this; | |
82 | } | |
1e59de90 | 83 | #ifndef mp_get_u64 |
f67539c2 | 84 | // Pick off 32 bit chunks for mp_set_int: |
1e59de90 | 85 | tommath_int& operator=(unsigned long long i) |
7c673cae | 86 | { |
92f5a8d4 | 87 | if (m_data.dp == 0) |
7c673cae | 88 | detail::check_tommath_result(mp_init(&m_data)); |
1e59de90 | 89 | unsigned long long mask = ((1uLL << 32) - 1); |
f67539c2 TL |
90 | unsigned shift = 0; |
91 | ::mp_int t; | |
7c673cae FG |
92 | detail::check_tommath_result(mp_init(&t)); |
93 | mp_zero(&m_data); | |
92f5a8d4 | 94 | while (i) |
7c673cae FG |
95 | { |
96 | detail::check_tommath_result(mp_set_int(&t, static_cast<unsigned>(i & mask))); | |
92f5a8d4 | 97 | if (shift) |
7c673cae FG |
98 | detail::check_tommath_result(mp_mul_2d(&t, shift, &t)); |
99 | detail::check_tommath_result((mp_add(&m_data, &t, &m_data))); | |
f67539c2 TL |
100 | shift += 32; |
101 | i >>= 32; | |
102 | } | |
103 | mp_clear(&t); | |
104 | return *this; | |
105 | } | |
106 | #elif !defined(ULLONG_MAX) || (ULLONG_MAX != 18446744073709551615uLL) | |
1e59de90 TL |
107 | // Pick off 64 bit chunks for mp_set_u64: |
108 | tommath_int& operator=(unsigned long long i) | |
f67539c2 TL |
109 | { |
110 | if (m_data.dp == 0) | |
111 | detail::check_tommath_result(mp_init(&m_data)); | |
1e59de90 | 112 | if(sizeof(unsigned long long) * CHAR_BIT == 64) |
f67539c2 TL |
113 | { |
114 | mp_set_u64(&m_data, i); | |
115 | return *this; | |
116 | } | |
1e59de90 | 117 | unsigned long long mask = ((1uLL << 64) - 1); |
f67539c2 TL |
118 | unsigned shift = 0; |
119 | ::mp_int t; | |
120 | detail::check_tommath_result(mp_init(&t)); | |
121 | mp_zero(&m_data); | |
122 | while (i) | |
123 | { | |
1e59de90 | 124 | detail::check_tommath_result(mp_set_u64(&t, static_cast<std::uint64_t>(i & mask))); |
f67539c2 TL |
125 | if (shift) |
126 | detail::check_tommath_result(mp_mul_2d(&t, shift, &t)); | |
127 | detail::check_tommath_result((mp_add(&m_data, &t, &m_data))); | |
128 | shift += 64; | |
129 | i >>= 64; | |
7c673cae FG |
130 | } |
131 | mp_clear(&t); | |
132 | return *this; | |
133 | } | |
f67539c2 | 134 | #else |
1e59de90 | 135 | tommath_int& operator=(unsigned long long i) |
f67539c2 TL |
136 | { |
137 | if (m_data.dp == 0) | |
138 | detail::check_tommath_result(mp_init(&m_data)); | |
139 | mp_set_u64(&m_data, i); | |
140 | return *this; | |
141 | } | |
142 | #endif | |
1e59de90 | 143 | tommath_int& operator=(long long i) |
7c673cae | 144 | { |
92f5a8d4 | 145 | if (m_data.dp == 0) |
7c673cae FG |
146 | detail::check_tommath_result(mp_init(&m_data)); |
147 | bool neg = i < 0; | |
92f5a8d4 TL |
148 | *this = boost::multiprecision::detail::unsigned_abs(i); |
149 | if (neg) | |
7c673cae FG |
150 | detail::check_tommath_result(mp_neg(&m_data, &m_data)); |
151 | return *this; | |
152 | } | |
1e59de90 TL |
153 | #ifdef BOOST_HAS_INT128 |
154 | // Pick off 64 bit chunks for mp_set_u64: | |
155 | tommath_int& operator=(uint128_type i) | |
156 | { | |
157 | if (m_data.dp == 0) | |
158 | detail::check_tommath_result(mp_init(&m_data)); | |
159 | ||
160 | int128_type mask = ((static_cast<uint128_type>(1u) << 64) - 1); | |
161 | unsigned shift = 0; | |
162 | ::mp_int t; | |
163 | detail::check_tommath_result(mp_init(&t)); | |
164 | mp_zero(&m_data); | |
165 | while (i) | |
166 | { | |
167 | #ifndef mp_get_u32 | |
168 | detail::check_tommath_result(mp_set_long_long(&t, static_cast<std::uint64_t>(i & mask))); | |
169 | #else | |
170 | mp_set_u64(&t, static_cast<std::uint64_t>(i & mask)); | |
171 | #endif | |
172 | if (shift) | |
173 | detail::check_tommath_result(mp_mul_2d(&t, shift, &t)); | |
174 | detail::check_tommath_result((mp_add(&m_data, &t, &m_data))); | |
175 | shift += 64; | |
176 | i >>= 64; | |
177 | } | |
178 | mp_clear(&t); | |
179 | return *this; | |
180 | } | |
181 | tommath_int& operator=(int128_type i) | |
182 | { | |
183 | if (m_data.dp == 0) | |
184 | detail::check_tommath_result(mp_init(&m_data)); | |
185 | bool neg = i < 0; | |
186 | *this = boost::multiprecision::detail::unsigned_abs(i); | |
187 | if (neg) | |
188 | detail::check_tommath_result(mp_neg(&m_data, &m_data)); | |
189 | return *this; | |
190 | } | |
191 | #endif | |
7c673cae FG |
192 | // |
193 | // Note that although mp_set_int takes an unsigned long as an argument | |
194 | // it only sets the first 32-bits to the result, and ignores the rest. | |
195 | // So use uint32_t as the largest type to pass to this function. | |
196 | // | |
1e59de90 | 197 | tommath_int& operator=(std::uint32_t i) |
7c673cae | 198 | { |
92f5a8d4 | 199 | if (m_data.dp == 0) |
7c673cae | 200 | detail::check_tommath_result(mp_init(&m_data)); |
1e59de90 | 201 | #ifndef mp_get_u32 |
7c673cae | 202 | detail::check_tommath_result((mp_set_int(&m_data, i))); |
f67539c2 TL |
203 | #else |
204 | mp_set_u32(&m_data, i); | |
205 | #endif | |
7c673cae FG |
206 | return *this; |
207 | } | |
1e59de90 | 208 | tommath_int& operator=(std::int32_t i) |
7c673cae | 209 | { |
92f5a8d4 | 210 | if (m_data.dp == 0) |
7c673cae FG |
211 | detail::check_tommath_result(mp_init(&m_data)); |
212 | bool neg = i < 0; | |
92f5a8d4 TL |
213 | *this = boost::multiprecision::detail::unsigned_abs(i); |
214 | if (neg) | |
7c673cae FG |
215 | detail::check_tommath_result(mp_neg(&m_data, &m_data)); |
216 | return *this; | |
217 | } | |
1e59de90 TL |
218 | template <class F> |
219 | tommath_int& assign_float(F a) | |
7c673cae | 220 | { |
1e59de90 | 221 | BOOST_MP_FLOAT128_USING using std::floor; using std::frexp; using std::ldexp; |
7c673cae | 222 | |
92f5a8d4 | 223 | if (m_data.dp == 0) |
7c673cae FG |
224 | detail::check_tommath_result(mp_init(&m_data)); |
225 | ||
92f5a8d4 TL |
226 | if (a == 0) |
227 | { | |
1e59de90 | 228 | #ifndef mp_get_u32 |
7c673cae | 229 | detail::check_tommath_result(mp_set_int(&m_data, 0)); |
f67539c2 TL |
230 | #else |
231 | mp_set_i32(&m_data, 0); | |
232 | #endif | |
7c673cae FG |
233 | return *this; |
234 | } | |
235 | ||
92f5a8d4 TL |
236 | if (a == 1) |
237 | { | |
1e59de90 | 238 | #ifndef mp_get_u32 |
7c673cae | 239 | detail::check_tommath_result(mp_set_int(&m_data, 1)); |
f67539c2 TL |
240 | #else |
241 | mp_set_i32(&m_data, 1); | |
242 | #endif | |
7c673cae FG |
243 | return *this; |
244 | } | |
245 | ||
1e59de90 TL |
246 | BOOST_MP_ASSERT(!BOOST_MP_ISINF(a)); |
247 | BOOST_MP_ASSERT(!BOOST_MP_ISNAN(a)); | |
7c673cae | 248 | |
92f5a8d4 | 249 | int e; |
1e59de90 TL |
250 | F f, term; |
251 | #ifndef mp_get_u32 | |
7c673cae | 252 | detail::check_tommath_result(mp_set_int(&m_data, 0u)); |
f67539c2 TL |
253 | #else |
254 | mp_set_i32(&m_data, 0); | |
255 | #endif | |
7c673cae FG |
256 | ::mp_int t; |
257 | detail::check_tommath_result(mp_init(&t)); | |
258 | ||
259 | f = frexp(a, &e); | |
260 | ||
1e59de90 TL |
261 | #ifdef MP_DIGIT_BIT |
262 | constexpr const int shift = std::numeric_limits<int>::digits - 1; | |
263 | using part_type = int ; | |
f67539c2 | 264 | #else |
1e59de90 TL |
265 | constexpr const int shift = std::numeric_limits<std::int64_t>::digits - 1; |
266 | using part_type = std::int64_t; | |
f67539c2 | 267 | #endif |
7c673cae | 268 | |
92f5a8d4 | 269 | while (f) |
7c673cae FG |
270 | { |
271 | // extract int sized bits from f: | |
92f5a8d4 | 272 | f = ldexp(f, shift); |
7c673cae FG |
273 | term = floor(f); |
274 | e -= shift; | |
275 | detail::check_tommath_result(mp_mul_2d(&m_data, shift, &m_data)); | |
92f5a8d4 | 276 | if (term > 0) |
7c673cae | 277 | { |
1e59de90 | 278 | #ifndef mp_get_u64 |
f67539c2 TL |
279 | detail::check_tommath_result(mp_set_int(&t, static_cast<part_type>(term))); |
280 | #else | |
281 | mp_set_i64(&t, static_cast<part_type>(term)); | |
282 | #endif | |
7c673cae FG |
283 | detail::check_tommath_result(mp_add(&m_data, &t, &m_data)); |
284 | } | |
285 | else | |
286 | { | |
1e59de90 | 287 | #ifndef mp_get_u64 |
f67539c2 TL |
288 | detail::check_tommath_result(mp_set_int(&t, static_cast<part_type>(-term))); |
289 | #else | |
290 | mp_set_i64(&t, static_cast<part_type>(-term)); | |
291 | #endif | |
7c673cae FG |
292 | detail::check_tommath_result(mp_sub(&m_data, &t, &m_data)); |
293 | } | |
294 | f -= term; | |
295 | } | |
92f5a8d4 | 296 | if (e > 0) |
7c673cae | 297 | detail::check_tommath_result(mp_mul_2d(&m_data, e, &m_data)); |
92f5a8d4 | 298 | else if (e < 0) |
7c673cae FG |
299 | { |
300 | tommath_int t2; | |
301 | detail::check_tommath_result(mp_div_2d(&m_data, -e, &m_data, &t2.data())); | |
302 | } | |
303 | mp_clear(&t); | |
304 | return *this; | |
305 | } | |
1e59de90 TL |
306 | tommath_int& operator=(long double a) |
307 | { | |
308 | return assign_float(a); | |
309 | } | |
310 | #ifdef BOOST_HAS_FLOAT128 | |
311 | tommath_int& operator= (float128_type a) | |
312 | { | |
313 | return assign_float(a); | |
314 | } | |
315 | #endif | |
92f5a8d4 | 316 | tommath_int& operator=(const char* s) |
7c673cae FG |
317 | { |
318 | // | |
319 | // We don't use libtommath's own routine because it doesn't error check the input :-( | |
320 | // | |
92f5a8d4 | 321 | if (m_data.dp == 0) |
7c673cae | 322 | detail::check_tommath_result(mp_init(&m_data)); |
92f5a8d4 | 323 | std::size_t n = s ? std::strlen(s) : 0; |
1e59de90 | 324 | *this = static_cast<std::uint32_t>(0u); |
7c673cae | 325 | unsigned radix = 10; |
92f5a8d4 TL |
326 | bool isneg = false; |
327 | if (n && (*s == '-')) | |
7c673cae FG |
328 | { |
329 | --n; | |
330 | ++s; | |
331 | isneg = true; | |
332 | } | |
92f5a8d4 | 333 | if (n && (*s == '0')) |
7c673cae | 334 | { |
92f5a8d4 | 335 | if ((n > 1) && ((s[1] == 'x') || (s[1] == 'X'))) |
7c673cae FG |
336 | { |
337 | radix = 16; | |
92f5a8d4 | 338 | s += 2; |
7c673cae FG |
339 | n -= 2; |
340 | } | |
341 | else | |
342 | { | |
343 | radix = 8; | |
344 | n -= 1; | |
345 | } | |
346 | } | |
92f5a8d4 | 347 | if (n) |
7c673cae | 348 | { |
92f5a8d4 | 349 | if (radix == 8 || radix == 16) |
7c673cae | 350 | { |
f67539c2 | 351 | unsigned shift = radix == 8 ? 3 : 4; |
1e59de90 | 352 | #ifndef MP_DIGIT_BIT |
f67539c2 TL |
353 | unsigned block_count = DIGIT_BIT / shift; |
354 | #else | |
355 | unsigned block_count = MP_DIGIT_BIT / shift; | |
356 | #endif | |
92f5a8d4 | 357 | unsigned block_shift = shift * block_count; |
1e59de90 | 358 | unsigned long long val, block; |
92f5a8d4 | 359 | while (*s) |
7c673cae FG |
360 | { |
361 | block = 0; | |
92f5a8d4 | 362 | for (unsigned i = 0; (i < block_count); ++i) |
7c673cae | 363 | { |
92f5a8d4 | 364 | if (*s >= '0' && *s <= '9') |
7c673cae | 365 | val = *s - '0'; |
92f5a8d4 | 366 | else if (*s >= 'a' && *s <= 'f') |
7c673cae | 367 | val = 10 + *s - 'a'; |
92f5a8d4 | 368 | else if (*s >= 'A' && *s <= 'F') |
7c673cae FG |
369 | val = 10 + *s - 'A'; |
370 | else | |
371 | val = 400; | |
92f5a8d4 | 372 | if (val > radix) |
7c673cae | 373 | { |
1e59de90 | 374 | BOOST_MP_THROW_EXCEPTION(std::runtime_error("Unexpected content found while parsing character string.")); |
7c673cae FG |
375 | } |
376 | block <<= shift; | |
377 | block |= val; | |
92f5a8d4 | 378 | if (!*++s) |
7c673cae FG |
379 | { |
380 | // final shift is different: | |
381 | block_shift = (i + 1) * shift; | |
382 | break; | |
383 | } | |
384 | } | |
385 | detail::check_tommath_result(mp_mul_2d(&data(), block_shift, &data())); | |
92f5a8d4 | 386 | if (data().used) |
7c673cae FG |
387 | data().dp[0] |= block; |
388 | else | |
389 | *this = block; | |
390 | } | |
391 | } | |
392 | else | |
393 | { | |
394 | // Base 10, we extract blocks of size 10^9 at a time, that way | |
395 | // the number of multiplications is kept to a minimum: | |
1e59de90 | 396 | std::uint32_t block_mult = 1000000000; |
92f5a8d4 | 397 | while (*s) |
7c673cae | 398 | { |
1e59de90 | 399 | std::uint32_t block = 0; |
92f5a8d4 | 400 | for (unsigned i = 0; i < 9; ++i) |
7c673cae | 401 | { |
1e59de90 | 402 | std::uint32_t val; |
92f5a8d4 | 403 | if (*s >= '0' && *s <= '9') |
7c673cae FG |
404 | val = *s - '0'; |
405 | else | |
1e59de90 | 406 | BOOST_MP_THROW_EXCEPTION(std::runtime_error("Unexpected character encountered in input.")); |
7c673cae FG |
407 | block *= 10; |
408 | block += val; | |
92f5a8d4 | 409 | if (!*++s) |
7c673cae | 410 | { |
1e59de90 | 411 | constexpr const std::uint32_t block_multiplier[9] = {10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; |
92f5a8d4 | 412 | block_mult = block_multiplier[i]; |
7c673cae FG |
413 | break; |
414 | } | |
415 | } | |
416 | tommath_int t; | |
417 | t = block_mult; | |
418 | eval_multiply(*this, t); | |
419 | t = block; | |
420 | eval_add(*this, t); | |
421 | } | |
422 | } | |
423 | } | |
92f5a8d4 | 424 | if (isneg) |
7c673cae FG |
425 | this->negate(); |
426 | return *this; | |
427 | } | |
92f5a8d4 | 428 | std::string str(std::streamsize /*digits*/, std::ios_base::fmtflags f) const |
7c673cae | 429 | { |
1e59de90 | 430 | BOOST_MP_ASSERT(m_data.dp); |
7c673cae | 431 | int base = 10; |
92f5a8d4 | 432 | if ((f & std::ios_base::oct) == std::ios_base::oct) |
7c673cae | 433 | base = 8; |
92f5a8d4 | 434 | else if ((f & std::ios_base::hex) == std::ios_base::hex) |
7c673cae FG |
435 | base = 16; |
436 | // | |
437 | // sanity check, bases 8 and 16 are only available for positive numbers: | |
438 | // | |
92f5a8d4 | 439 | if ((base != 10) && m_data.sign) |
1e59de90 TL |
440 | BOOST_MP_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers")); |
441 | ||
7c673cae FG |
442 | int s; |
443 | detail::check_tommath_result(mp_radix_size(const_cast< ::mp_int*>(&m_data), base, &s)); | |
1e59de90 TL |
444 | std::unique_ptr<char[]> a(new char[s + 1]); |
445 | #ifndef mp_to_binary | |
92f5a8d4 | 446 | detail::check_tommath_result(mp_toradix_n(const_cast< ::mp_int*>(&m_data), a.get(), base, s + 1)); |
f67539c2 TL |
447 | #else |
448 | std::size_t written; | |
449 | detail::check_tommath_result(mp_to_radix(&m_data, a.get(), s + 1, &written, base)); | |
450 | #endif | |
7c673cae | 451 | std::string result = a.get(); |
92f5a8d4 TL |
452 | if (f & std::ios_base::uppercase) |
453 | for (size_t i = 0; i < result.length(); ++i) | |
454 | result[i] = std::toupper(result[i]); | |
455 | if ((base != 10) && (f & std::ios_base::showbase)) | |
7c673cae | 456 | { |
92f5a8d4 TL |
457 | int pos = result[0] == '-' ? 1 : 0; |
458 | const char* pp = base == 8 ? "0" : (f & std::ios_base::uppercase) ? "0X" : "0x"; | |
7c673cae FG |
459 | result.insert(static_cast<std::string::size_type>(pos), pp); |
460 | } | |
92f5a8d4 | 461 | if ((f & std::ios_base::showpos) && (result[0] != '-')) |
7c673cae | 462 | result.insert(static_cast<std::string::size_type>(0), 1, '+'); |
f67539c2 TL |
463 | if (((f & std::ios_base::uppercase) == 0) && (base == 16)) |
464 | { | |
465 | for (std::size_t i = 0; i < result.size(); ++i) | |
466 | result[i] = std::tolower(result[i]); | |
467 | } | |
7c673cae FG |
468 | return result; |
469 | } | |
470 | ~tommath_int() | |
471 | { | |
92f5a8d4 | 472 | if (m_data.dp) |
7c673cae FG |
473 | mp_clear(&m_data); |
474 | } | |
475 | void negate() | |
476 | { | |
1e59de90 | 477 | BOOST_MP_ASSERT(m_data.dp); |
f67539c2 | 478 | detail::check_tommath_result(mp_neg(&m_data, &m_data)); |
7c673cae | 479 | } |
92f5a8d4 | 480 | int compare(const tommath_int& o) const |
7c673cae | 481 | { |
1e59de90 | 482 | BOOST_MP_ASSERT(m_data.dp && o.m_data.dp); |
7c673cae FG |
483 | return mp_cmp(const_cast< ::mp_int*>(&m_data), const_cast< ::mp_int*>(&o.m_data)); |
484 | } | |
485 | template <class V> | |
92f5a8d4 | 486 | int compare(V v) const |
7c673cae FG |
487 | { |
488 | tommath_int d; | |
489 | tommath_int t(*this); | |
490 | detail::check_tommath_result(mp_shrink(&t.data())); | |
491 | d = v; | |
492 | return t.compare(d); | |
493 | } | |
92f5a8d4 TL |
494 | ::mp_int& data() |
495 | { | |
1e59de90 | 496 | BOOST_MP_ASSERT(m_data.dp); |
92f5a8d4 | 497 | return m_data; |
7c673cae | 498 | } |
92f5a8d4 TL |
499 | const ::mp_int& data() const |
500 | { | |
1e59de90 | 501 | BOOST_MP_ASSERT(m_data.dp); |
92f5a8d4 | 502 | return m_data; |
7c673cae | 503 | } |
1e59de90 | 504 | void swap(tommath_int& o) noexcept |
7c673cae FG |
505 | { |
506 | mp_exch(&m_data, &o.data()); | |
507 | } | |
92f5a8d4 TL |
508 | |
509 | protected: | |
7c673cae FG |
510 | ::mp_int m_data; |
511 | }; | |
512 | ||
1e59de90 | 513 | #ifndef mp_isneg |
92f5a8d4 TL |
514 | #define BOOST_MP_TOMMATH_BIT_OP_CHECK(x) \ |
515 | if (SIGN(&x.data())) \ | |
1e59de90 | 516 | BOOST_MP_THROW_EXCEPTION(std::runtime_error("Bitwise operations on libtommath negative valued integers are disabled as they produce unpredictable results")) |
f67539c2 TL |
517 | #else |
518 | #define BOOST_MP_TOMMATH_BIT_OP_CHECK(x) \ | |
519 | if (mp_isneg(&x.data())) \ | |
1e59de90 | 520 | BOOST_MP_THROW_EXCEPTION(std::runtime_error("Bitwise operations on libtommath negative valued integers are disabled as they produce unpredictable results")) |
f67539c2 | 521 | #endif |
7c673cae FG |
522 | |
523 | int eval_get_sign(const tommath_int& val); | |
524 | ||
525 | inline void eval_add(tommath_int& t, const tommath_int& o) | |
526 | { | |
527 | detail::check_tommath_result(mp_add(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); | |
528 | } | |
529 | inline void eval_subtract(tommath_int& t, const tommath_int& o) | |
530 | { | |
531 | detail::check_tommath_result(mp_sub(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); | |
532 | } | |
533 | inline void eval_multiply(tommath_int& t, const tommath_int& o) | |
534 | { | |
535 | detail::check_tommath_result(mp_mul(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); | |
536 | } | |
537 | inline void eval_divide(tommath_int& t, const tommath_int& o) | |
538 | { | |
539 | using default_ops::eval_is_zero; | |
540 | tommath_int temp; | |
92f5a8d4 | 541 | if (eval_is_zero(o)) |
1e59de90 | 542 | BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero")); |
7c673cae FG |
543 | detail::check_tommath_result(mp_div(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data(), &temp.data())); |
544 | } | |
545 | inline void eval_modulus(tommath_int& t, const tommath_int& o) | |
546 | { | |
547 | using default_ops::eval_is_zero; | |
92f5a8d4 | 548 | if (eval_is_zero(o)) |
1e59de90 | 549 | BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero")); |
92f5a8d4 | 550 | bool neg = eval_get_sign(t) < 0; |
7c673cae FG |
551 | bool neg2 = eval_get_sign(o) < 0; |
552 | detail::check_tommath_result(mp_mod(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); | |
92f5a8d4 | 553 | if ((neg != neg2) && (eval_get_sign(t) != 0)) |
7c673cae FG |
554 | { |
555 | t.negate(); | |
556 | detail::check_tommath_result(mp_add(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); | |
557 | t.negate(); | |
558 | } | |
92f5a8d4 | 559 | else if (neg && (t.compare(o) == 0)) |
7c673cae FG |
560 | { |
561 | mp_zero(&t.data()); | |
562 | } | |
563 | } | |
564 | template <class UI> | |
565 | inline void eval_left_shift(tommath_int& t, UI i) | |
566 | { | |
567 | detail::check_tommath_result(mp_mul_2d(&t.data(), static_cast<unsigned>(i), &t.data())); | |
568 | } | |
569 | template <class UI> | |
570 | inline void eval_right_shift(tommath_int& t, UI i) | |
571 | { | |
7c673cae | 572 | using default_ops::eval_decrement; |
92f5a8d4 TL |
573 | using default_ops::eval_increment; |
574 | bool neg = eval_get_sign(t) < 0; | |
7c673cae | 575 | tommath_int d; |
92f5a8d4 | 576 | if (neg) |
7c673cae FG |
577 | eval_increment(t); |
578 | detail::check_tommath_result(mp_div_2d(&t.data(), static_cast<unsigned>(i), &t.data(), &d.data())); | |
92f5a8d4 | 579 | if (neg) |
7c673cae FG |
580 | eval_decrement(t); |
581 | } | |
582 | template <class UI> | |
583 | inline void eval_left_shift(tommath_int& t, const tommath_int& v, UI i) | |
584 | { | |
585 | detail::check_tommath_result(mp_mul_2d(const_cast< ::mp_int*>(&v.data()), static_cast<unsigned>(i), &t.data())); | |
586 | } | |
587 | /* | |
588 | template <class UI> | |
589 | inline void eval_right_shift(tommath_int& t, const tommath_int& v, UI i) | |
590 | { | |
591 | tommath_int d; | |
592 | detail::check_tommath_result(mp_div_2d(const_cast< ::mp_int*>(&v.data()), static_cast<unsigned long>(i), &t.data(), &d.data())); | |
593 | } | |
594 | */ | |
595 | inline void eval_bitwise_and(tommath_int& result, const tommath_int& v) | |
596 | { | |
597 | BOOST_MP_TOMMATH_BIT_OP_CHECK(result); | |
598 | BOOST_MP_TOMMATH_BIT_OP_CHECK(v); | |
599 | detail::check_tommath_result(mp_and(&result.data(), const_cast< ::mp_int*>(&v.data()), &result.data())); | |
600 | } | |
601 | ||
602 | inline void eval_bitwise_or(tommath_int& result, const tommath_int& v) | |
603 | { | |
604 | BOOST_MP_TOMMATH_BIT_OP_CHECK(result); | |
605 | BOOST_MP_TOMMATH_BIT_OP_CHECK(v); | |
606 | detail::check_tommath_result(mp_or(&result.data(), const_cast< ::mp_int*>(&v.data()), &result.data())); | |
607 | } | |
608 | ||
609 | inline void eval_bitwise_xor(tommath_int& result, const tommath_int& v) | |
610 | { | |
611 | BOOST_MP_TOMMATH_BIT_OP_CHECK(result); | |
612 | BOOST_MP_TOMMATH_BIT_OP_CHECK(v); | |
613 | detail::check_tommath_result(mp_xor(&result.data(), const_cast< ::mp_int*>(&v.data()), &result.data())); | |
614 | } | |
615 | ||
616 | inline void eval_add(tommath_int& t, const tommath_int& p, const tommath_int& o) | |
617 | { | |
618 | detail::check_tommath_result(mp_add(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data())); | |
619 | } | |
620 | inline void eval_subtract(tommath_int& t, const tommath_int& p, const tommath_int& o) | |
621 | { | |
622 | detail::check_tommath_result(mp_sub(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data())); | |
623 | } | |
624 | inline void eval_multiply(tommath_int& t, const tommath_int& p, const tommath_int& o) | |
625 | { | |
626 | detail::check_tommath_result(mp_mul(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data())); | |
627 | } | |
628 | inline void eval_divide(tommath_int& t, const tommath_int& p, const tommath_int& o) | |
629 | { | |
630 | using default_ops::eval_is_zero; | |
631 | tommath_int d; | |
92f5a8d4 | 632 | if (eval_is_zero(o)) |
1e59de90 | 633 | BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero")); |
7c673cae FG |
634 | detail::check_tommath_result(mp_div(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data(), &d.data())); |
635 | } | |
636 | inline void eval_modulus(tommath_int& t, const tommath_int& p, const tommath_int& o) | |
637 | { | |
638 | using default_ops::eval_is_zero; | |
92f5a8d4 | 639 | if (eval_is_zero(o)) |
1e59de90 | 640 | BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero")); |
92f5a8d4 | 641 | bool neg = eval_get_sign(p) < 0; |
7c673cae FG |
642 | bool neg2 = eval_get_sign(o) < 0; |
643 | detail::check_tommath_result(mp_mod(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data())); | |
92f5a8d4 | 644 | if ((neg != neg2) && (eval_get_sign(t) != 0)) |
7c673cae FG |
645 | { |
646 | t.negate(); | |
647 | detail::check_tommath_result(mp_add(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data())); | |
648 | t.negate(); | |
649 | } | |
92f5a8d4 | 650 | else if (neg && (t.compare(o) == 0)) |
7c673cae FG |
651 | { |
652 | mp_zero(&t.data()); | |
653 | } | |
654 | } | |
655 | ||
656 | inline void eval_bitwise_and(tommath_int& result, const tommath_int& u, const tommath_int& v) | |
657 | { | |
658 | BOOST_MP_TOMMATH_BIT_OP_CHECK(u); | |
659 | BOOST_MP_TOMMATH_BIT_OP_CHECK(v); | |
660 | detail::check_tommath_result(mp_and(const_cast< ::mp_int*>(&u.data()), const_cast< ::mp_int*>(&v.data()), &result.data())); | |
661 | } | |
662 | ||
663 | inline void eval_bitwise_or(tommath_int& result, const tommath_int& u, const tommath_int& v) | |
664 | { | |
665 | BOOST_MP_TOMMATH_BIT_OP_CHECK(u); | |
666 | BOOST_MP_TOMMATH_BIT_OP_CHECK(v); | |
667 | detail::check_tommath_result(mp_or(const_cast< ::mp_int*>(&u.data()), const_cast< ::mp_int*>(&v.data()), &result.data())); | |
668 | } | |
669 | ||
670 | inline void eval_bitwise_xor(tommath_int& result, const tommath_int& u, const tommath_int& v) | |
671 | { | |
672 | BOOST_MP_TOMMATH_BIT_OP_CHECK(u); | |
673 | BOOST_MP_TOMMATH_BIT_OP_CHECK(v); | |
674 | detail::check_tommath_result(mp_xor(const_cast< ::mp_int*>(&u.data()), const_cast< ::mp_int*>(&v.data()), &result.data())); | |
675 | } | |
676 | /* | |
677 | inline void eval_complement(tommath_int& result, const tommath_int& u) | |
678 | { | |
679 | // | |
680 | // Although this code works, it doesn't really do what the user might expect.... | |
681 | // and it's hard to see how it ever could. Disabled for now: | |
682 | // | |
683 | result = u; | |
684 | for(int i = 0; i < result.data().used; ++i) | |
685 | { | |
686 | result.data().dp[i] = MP_MASK & ~(result.data().dp[i]); | |
687 | } | |
688 | // | |
689 | // We now need to pad out the left of the value with 1's to round up to a whole number of | |
690 | // CHAR_BIT * sizeof(mp_digit) units. Otherwise we'll end up with a very strange number of | |
691 | // bits set! | |
692 | // | |
693 | unsigned shift = result.data().used * DIGIT_BIT; // How many bits we're actually using | |
694 | // How many bits we actually need, reduced by one to account for a mythical sign bit: | |
695 | int padding = result.data().used * std::numeric_limits<mp_digit>::digits - shift - 1; | |
696 | while(padding >= std::numeric_limits<mp_digit>::digits) | |
697 | padding -= std::numeric_limits<mp_digit>::digits; | |
698 | ||
699 | // Create a mask providing the extra bits we need and add to result: | |
700 | tommath_int mask; | |
1e59de90 | 701 | mask = static_cast<long long>((1u << padding) - 1); |
7c673cae FG |
702 | eval_left_shift(mask, shift); |
703 | add(result, mask); | |
704 | } | |
705 | */ | |
706 | inline bool eval_is_zero(const tommath_int& val) | |
707 | { | |
708 | return mp_iszero(&val.data()); | |
709 | } | |
710 | inline int eval_get_sign(const tommath_int& val) | |
711 | { | |
1e59de90 | 712 | #ifndef mp_isneg |
7c673cae | 713 | return mp_iszero(&val.data()) ? 0 : SIGN(&val.data()) ? -1 : 1; |
f67539c2 TL |
714 | #else |
715 | return mp_iszero(&val.data()) ? 0 : mp_isneg(&val.data()) ? -1 : 1; | |
716 | #endif | |
7c673cae | 717 | } |
1e59de90 TL |
718 | |
719 | inline void eval_convert_to(unsigned long long* result, const tommath_int& val) | |
720 | { | |
721 | if (mp_isneg(&val.data())) | |
722 | { | |
723 | BOOST_MP_THROW_EXCEPTION(std::range_error("Converting negative arbitrary precision value to unsigned.")); | |
724 | } | |
725 | #ifdef MP_DEPRECATED | |
726 | *result = mp_get_ull(&val.data()); | |
727 | #else | |
728 | *result = mp_get_long_long(const_cast<mp_int*>(&val.data())); | |
729 | #endif | |
730 | } | |
731 | ||
732 | inline void eval_convert_to(long long* result, const tommath_int& val) | |
733 | { | |
734 | if (!mp_iszero(&val.data()) && (mp_count_bits(const_cast<::mp_int*>(&val.data())) > std::numeric_limits<long long>::digits)) | |
735 | { | |
736 | *result = mp_isneg(&val.data()) ? (std::numeric_limits<long long>::min)() : (std::numeric_limits<long long>::max)(); | |
737 | return; | |
738 | } | |
739 | #ifdef MP_DEPRECATED | |
740 | unsigned long long r = mp_get_mag_ull(&val.data()); | |
741 | #else | |
742 | unsigned long long r = mp_get_long_long(const_cast<mp_int*>(&val.data())); | |
743 | #endif | |
744 | if (mp_isneg(&val.data())) | |
745 | *result = -static_cast<long long>(r); | |
746 | else | |
747 | *result = r; | |
748 | } | |
749 | ||
750 | #ifdef BOOST_HAS_INT128 | |
751 | inline void eval_convert_to(uint128_type* result, const tommath_int& val) | |
752 | { | |
753 | #ifdef MP_DEPRECATED | |
754 | if (mp_ubin_size(&val.data()) > sizeof(uint128_type)) | |
755 | { | |
756 | *result = ~static_cast<uint128_type>(0); | |
757 | return; | |
758 | } | |
759 | unsigned char buf[sizeof(uint128_type)]; | |
760 | std::size_t len; | |
761 | detail::check_tommath_result(mp_to_ubin(&val.data(), buf, sizeof(buf), &len)); | |
762 | *result = 0; | |
763 | for (std::size_t i = 0; i < len; ++i) | |
764 | { | |
765 | *result <<= CHAR_BIT; | |
766 | *result |= buf[i]; | |
767 | } | |
768 | #else | |
769 | std::size_t len = mp_unsigned_bin_size(const_cast<mp_int*>(&val.data())); | |
770 | if (len > sizeof(uint128_type)) | |
771 | { | |
772 | *result = ~static_cast<uint128_type>(0); | |
773 | return; | |
774 | } | |
775 | unsigned char buf[sizeof(uint128_type)]; | |
776 | detail::check_tommath_result(mp_to_unsigned_bin(const_cast<mp_int*>(&val.data()), buf)); | |
777 | *result = 0; | |
778 | for (std::size_t i = 0; i < len; ++i) | |
779 | { | |
780 | *result <<= CHAR_BIT; | |
781 | *result |= buf[i]; | |
782 | } | |
783 | #endif | |
784 | } | |
785 | inline void eval_convert_to(int128_type* result, const tommath_int& val) | |
7c673cae | 786 | { |
1e59de90 TL |
787 | uint128_type r; |
788 | eval_convert_to(&r, val); | |
789 | if (mp_isneg(&val.data())) | |
790 | *result = -static_cast<int128_type>(r); | |
791 | else | |
792 | *result = r; | |
7c673cae | 793 | } |
1e59de90 TL |
794 | #endif |
795 | #if defined(BOOST_HAS_FLOAT128) | |
796 | inline void eval_convert_to(float128_type* result, const tommath_int& val) noexcept | |
7c673cae | 797 | { |
1e59de90 | 798 | *result = float128_procs::strtoflt128(val.str(0, std::ios_base::scientific).c_str(), nullptr); |
7c673cae | 799 | } |
1e59de90 TL |
800 | #endif |
801 | inline void eval_convert_to(long double* result, const tommath_int& val) noexcept | |
7c673cae | 802 | { |
1e59de90 | 803 | *result = std::strtold(val.str(0, std::ios_base::scientific).c_str(), nullptr); |
7c673cae | 804 | } |
1e59de90 | 805 | inline void eval_convert_to(double* result, const tommath_int& val) noexcept |
7c673cae | 806 | { |
1e59de90 | 807 | *result = std::strtod(val.str(0, std::ios_base::scientific).c_str(), nullptr); |
7c673cae | 808 | } |
1e59de90 TL |
809 | inline void eval_convert_to(float* result, const tommath_int& val) noexcept |
810 | { | |
811 | *result = std::strtof(val.str(0, std::ios_base::scientific).c_str(), nullptr); | |
812 | } | |
813 | ||
814 | ||
7c673cae FG |
815 | inline void eval_abs(tommath_int& result, const tommath_int& val) |
816 | { | |
817 | detail::check_tommath_result(mp_abs(const_cast< ::mp_int*>(&val.data()), &result.data())); | |
818 | } | |
819 | inline void eval_gcd(tommath_int& result, const tommath_int& a, const tommath_int& b) | |
820 | { | |
821 | detail::check_tommath_result(mp_gcd(const_cast< ::mp_int*>(&a.data()), const_cast< ::mp_int*>(&b.data()), const_cast< ::mp_int*>(&result.data()))); | |
822 | } | |
823 | inline void eval_lcm(tommath_int& result, const tommath_int& a, const tommath_int& b) | |
824 | { | |
825 | detail::check_tommath_result(mp_lcm(const_cast< ::mp_int*>(&a.data()), const_cast< ::mp_int*>(&b.data()), const_cast< ::mp_int*>(&result.data()))); | |
826 | } | |
827 | inline void eval_powm(tommath_int& result, const tommath_int& base, const tommath_int& p, const tommath_int& m) | |
828 | { | |
92f5a8d4 | 829 | if (eval_get_sign(p) < 0) |
7c673cae | 830 | { |
1e59de90 | 831 | BOOST_MP_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent.")); |
7c673cae FG |
832 | } |
833 | detail::check_tommath_result(mp_exptmod(const_cast< ::mp_int*>(&base.data()), const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&m.data()), &result.data())); | |
834 | } | |
835 | ||
92f5a8d4 TL |
836 | inline void eval_qr(const tommath_int& x, const tommath_int& y, |
837 | tommath_int& q, tommath_int& r) | |
7c673cae FG |
838 | { |
839 | detail::check_tommath_result(mp_div(const_cast< ::mp_int*>(&x.data()), const_cast< ::mp_int*>(&y.data()), &q.data(), &r.data())); | |
840 | } | |
841 | ||
1e59de90 | 842 | inline std::size_t eval_lsb(const tommath_int& val) |
7c673cae FG |
843 | { |
844 | int c = eval_get_sign(val); | |
92f5a8d4 | 845 | if (c == 0) |
7c673cae | 846 | { |
1e59de90 | 847 | BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand.")); |
7c673cae | 848 | } |
92f5a8d4 | 849 | if (c < 0) |
7c673cae | 850 | { |
1e59de90 | 851 | BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined.")); |
7c673cae FG |
852 | } |
853 | return mp_cnt_lsb(const_cast< ::mp_int*>(&val.data())); | |
854 | } | |
855 | ||
1e59de90 | 856 | inline std::size_t eval_msb(const tommath_int& val) |
7c673cae FG |
857 | { |
858 | int c = eval_get_sign(val); | |
92f5a8d4 | 859 | if (c == 0) |
7c673cae | 860 | { |
1e59de90 | 861 | BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand.")); |
7c673cae | 862 | } |
92f5a8d4 | 863 | if (c < 0) |
7c673cae | 864 | { |
1e59de90 | 865 | BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined.")); |
7c673cae FG |
866 | } |
867 | return mp_count_bits(const_cast< ::mp_int*>(&val.data())) - 1; | |
868 | } | |
869 | ||
870 | template <class Integer> | |
1e59de90 | 871 | inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<Integer>::value, Integer>::type eval_integer_modulus(const tommath_int& x, Integer val) |
7c673cae | 872 | { |
1e59de90 TL |
873 | #ifndef MP_DIGIT_BIT |
874 | constexpr const mp_digit m = (static_cast<mp_digit>(1) << DIGIT_BIT) - 1; | |
f67539c2 | 875 | #else |
1e59de90 | 876 | constexpr const mp_digit m = (static_cast<mp_digit>(1) << MP_DIGIT_BIT) - 1; |
f67539c2 | 877 | #endif |
92f5a8d4 | 878 | if (val <= m) |
7c673cae FG |
879 | { |
880 | mp_digit d; | |
881 | detail::check_tommath_result(mp_mod_d(const_cast< ::mp_int*>(&x.data()), static_cast<mp_digit>(val), &d)); | |
882 | return d; | |
883 | } | |
884 | else | |
885 | { | |
886 | return default_ops::eval_integer_modulus(x, val); | |
887 | } | |
888 | } | |
889 | template <class Integer> | |
1e59de90 | 890 | inline typename std::enable_if<boost::multiprecision::detail::is_signed<Integer>::value && boost::multiprecision::detail::is_integral<Integer>::value, Integer>::type eval_integer_modulus(const tommath_int& x, Integer val) |
7c673cae FG |
891 | { |
892 | return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val)); | |
893 | } | |
894 | ||
895 | inline std::size_t hash_value(const tommath_int& val) | |
896 | { | |
897 | std::size_t result = 0; | |
92f5a8d4 TL |
898 | std::size_t len = val.data().used; |
899 | for (std::size_t i = 0; i < len; ++i) | |
1e59de90 TL |
900 | boost::multiprecision::detail::hash_combine(result, val.data().dp[i]); |
901 | boost::multiprecision::detail::hash_combine(result, val.data().sign); | |
7c673cae FG |
902 | return result; |
903 | } | |
904 | ||
905 | } // namespace backends | |
906 | ||
907 | using boost::multiprecision::backends::tommath_int; | |
908 | ||
92f5a8d4 | 909 | template <> |
1e59de90 | 910 | struct number_category<tommath_int> : public std::integral_constant<int, number_kind_integer> |
92f5a8d4 | 911 | {}; |
7c673cae | 912 | |
1e59de90 TL |
913 | using tom_int = number<tommath_int> ; |
914 | using tommath_rational = rational_adaptor<tommath_int>; | |
915 | using tom_rational = number<tommath_rational> ; | |
f67539c2 TL |
916 | } |
917 | } // namespace boost::multiprecision | |
7c673cae | 918 | |
92f5a8d4 | 919 | namespace std { |
7c673cae | 920 | |
92f5a8d4 | 921 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
7c673cae FG |
922 | class numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> > |
923 | { | |
1e59de90 | 924 | using number_type = boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates>; |
92f5a8d4 TL |
925 | |
926 | public: | |
1e59de90 | 927 | static constexpr bool is_specialized = true; |
7c673cae FG |
928 | // |
929 | // Largest and smallest numbers are bounded only by available memory, set | |
930 | // to zero: | |
931 | // | |
92f5a8d4 TL |
932 | static number_type(min)() |
933 | { | |
7c673cae FG |
934 | return number_type(); |
935 | } | |
92f5a8d4 TL |
936 | static number_type(max)() |
937 | { | |
7c673cae FG |
938 | return number_type(); |
939 | } | |
f67539c2 | 940 | static number_type lowest() { return (min)(); } |
1e59de90 TL |
941 | static constexpr int digits = INT_MAX; |
942 | static constexpr int digits10 = (INT_MAX / 1000) * 301L; | |
943 | static constexpr int max_digits10 = digits10 + 3; | |
944 | static constexpr bool is_signed = true; | |
945 | static constexpr bool is_integer = true; | |
946 | static constexpr bool is_exact = true; | |
947 | static constexpr int radix = 2; | |
f67539c2 TL |
948 | static number_type epsilon() { return number_type(); } |
949 | static number_type round_error() { return number_type(); } | |
1e59de90 TL |
950 | static constexpr int min_exponent = 0; |
951 | static constexpr int min_exponent10 = 0; | |
952 | static constexpr int max_exponent = 0; | |
953 | static constexpr int max_exponent10 = 0; | |
954 | static constexpr bool has_infinity = false; | |
955 | static constexpr bool has_quiet_NaN = false; | |
956 | static constexpr bool has_signaling_NaN = false; | |
957 | static constexpr float_denorm_style has_denorm = denorm_absent; | |
958 | static constexpr bool has_denorm_loss = false; | |
92f5a8d4 TL |
959 | static number_type infinity() { return number_type(); } |
960 | static number_type quiet_NaN() { return number_type(); } | |
961 | static number_type signaling_NaN() { return number_type(); } | |
962 | static number_type denorm_min() { return number_type(); } | |
1e59de90 TL |
963 | static constexpr bool is_iec559 = false; |
964 | static constexpr bool is_bounded = false; | |
965 | static constexpr bool is_modulo = false; | |
966 | static constexpr bool traps = false; | |
967 | static constexpr bool tinyness_before = false; | |
968 | static constexpr float_round_style round_style = round_toward_zero; | |
7c673cae FG |
969 | }; |
970 | ||
7c673cae | 971 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 972 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::digits; |
7c673cae | 973 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 974 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::digits10; |
7c673cae | 975 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 976 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::max_digits10; |
7c673cae | 977 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 978 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::is_signed; |
7c673cae | 979 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 980 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::is_integer; |
7c673cae | 981 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 982 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::is_exact; |
7c673cae | 983 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 984 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::radix; |
7c673cae | 985 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 986 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::min_exponent; |
7c673cae | 987 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 988 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::min_exponent10; |
7c673cae | 989 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 990 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::max_exponent; |
7c673cae | 991 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 992 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::max_exponent10; |
7c673cae | 993 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 994 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::has_infinity; |
7c673cae | 995 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 996 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::has_quiet_NaN; |
7c673cae | 997 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 998 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::has_signaling_NaN; |
7c673cae | 999 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 1000 | constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::has_denorm; |
7c673cae | 1001 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 1002 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::has_denorm_loss; |
7c673cae | 1003 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 1004 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::is_iec559; |
7c673cae | 1005 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 1006 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::is_bounded; |
7c673cae | 1007 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 1008 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::is_modulo; |
7c673cae | 1009 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 1010 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::traps; |
7c673cae | 1011 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 1012 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::tinyness_before; |
7c673cae | 1013 | template <boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 1014 | constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::tommath_int, ExpressionTemplates> >::round_style; |
7c673cae | 1015 | |
92f5a8d4 | 1016 | } // namespace std |
7c673cae FG |
1017 | |
1018 | #endif |