1 ///////////////////////////////////////////////////////////////
2 // Copyright 2012 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_
6 // Comparison operators for cpp_int_backend:
8 #ifndef BOOST_MP_CPP_INT_MISC_HPP
9 #define BOOST_MP_CPP_INT_MISC_HPP
11 #include <boost/multiprecision/detail/bitscan.hpp> // lsb etc
12 #include <boost/integer/common_factor_rt.hpp> // gcd/lcm
13 #include <boost/functional/hash_fwd.hpp>
17 #pragma warning(disable:4702)
18 #pragma warning(disable:4127) // conditional expression is constant
19 #pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned
23 namespace boost{ namespace multiprecision{ namespace backends{
25 template <class R, class CppInt>
26 void check_in_range(const CppInt& val, const mpl::int_<checked>&)
28 typedef typename boost::multiprecision::detail::canonical<R, CppInt>::type cast_type;
31 if(val.compare(static_cast<cast_type>((std::numeric_limits<R>::min)())) < 0)
32 BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
36 if(val.compare(static_cast<cast_type>((std::numeric_limits<R>::max)())) > 0)
37 BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range."));
40 template <class R, class CppInt>
41 inline void check_in_range(const CppInt& /*val*/, const mpl::int_<unchecked>&) BOOST_NOEXCEPT {}
43 inline void check_is_negative(const mpl::true_&) BOOST_NOEXCEPT {}
44 inline void check_is_negative(const mpl::false_&)
46 BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
49 template <class Integer>
50 inline Integer negate_integer(Integer i, const mpl::true_&) BOOST_NOEXCEPT
54 template <class Integer>
55 inline Integer negate_integer(Integer i, const mpl::false_&) BOOST_NOEXCEPT
60 template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
61 inline typename enable_if_c<is_integral<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
62 eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
64 typedef mpl::int_<Checked1> checked_type;
65 check_in_range<R>(backend, checked_type());
67 *result = static_cast<R>(backend.limbs()[0]);
68 unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
69 for(unsigned i = 1; (i < backend.size()) && (shift < static_cast<unsigned>(std::numeric_limits<R>::digits)); ++i)
71 *result += static_cast<R>(backend.limbs()[i]) << shift;
72 shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
76 check_is_negative(boost::is_signed<R>());
77 *result = negate_integer(*result, boost::is_signed<R>());
81 template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
82 inline typename enable_if_c<is_floating_point<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type
83 eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) BOOST_MP_NOEXCEPT_IF(is_arithmetic<R>::value)
85 typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p = backend.limbs();
86 unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
87 *result = static_cast<R>(*p);
88 for(unsigned i = 1; i < backend.size(); ++i)
90 *result += static_cast<R>(std::ldexp(static_cast<long double>(p[i]), shift));
91 shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
97 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
98 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
99 eval_is_zero(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
101 return (val.size() == 1) && (val.limbs()[0] == 0);
103 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
104 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, int>::type
105 eval_get_sign(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
107 return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1;
109 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
110 BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
111 eval_abs(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
118 // Get the location of the least-significant-bit:
120 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
121 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
122 eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
124 using default_ops::eval_get_sign;
125 if(eval_get_sign(a) == 0)
127 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
131 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
135 // Find the index of the least significant limb that is non-zero:
138 while(!a.limbs()[index] && (index < a.size()))
141 // Find the index of the least significant bit within that limb:
143 unsigned result = boost::multiprecision::detail::find_lsb(a.limbs()[index]);
145 return result + index * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
149 // Get the location of the most-significant-bit:
151 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
152 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
153 eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
156 // Find the index of the most significant bit that is non-zero:
158 return (a.size() - 1) * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]);
161 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
162 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
163 eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
165 using default_ops::eval_get_sign;
166 if(eval_get_sign(a) == 0)
168 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
172 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
174 return eval_msb_imp(a);
177 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
178 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type
179 eval_bit_test(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT
181 unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
182 unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
183 limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
184 if(offset >= val.size())
186 return val.limbs()[offset] & mask ? true : false;
189 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
190 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
191 eval_bit_set(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index)
193 unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
194 unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
195 limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
196 if(offset >= val.size())
198 unsigned os = val.size();
199 val.resize(offset + 1, offset + 1);
200 if(offset >= val.size())
201 return; // fixed precision overflow
202 for(unsigned i = os; i <= offset; ++i)
205 val.limbs()[offset] |= mask;
208 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
209 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
210 eval_bit_unset(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT
212 unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
213 unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
214 limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
215 if(offset >= val.size())
217 val.limbs()[offset] &= ~mask;
221 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
222 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
223 eval_bit_flip(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index)
225 unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
226 unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
227 limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u);
228 if(offset >= val.size())
230 unsigned os = val.size();
231 val.resize(offset + 1, offset + 1);
232 if(offset >= val.size())
233 return; // fixed precision overflow
234 for(unsigned i = os; i <= offset; ++i)
237 val.limbs()[offset] ^= mask;
241 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
242 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
244 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
245 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& y,
246 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
247 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
249 divide_unsigned_helper(&q, x, y, r);
250 q.sign(x.sign() != y.sign());
254 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
255 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
257 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
259 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
260 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
262 divide_unsigned_helper(&q, x, y, r);
267 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class U>
268 inline typename enable_if_c<is_integral<U>::value>::type eval_qr(
269 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
271 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q,
272 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
274 using default_ops::eval_qr;
275 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
280 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
281 inline typename enable_if_c<is_unsigned<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
282 eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
284 if((sizeof(Integer) <= sizeof(limb_type)) || (val <= (std::numeric_limits<limb_type>::max)()))
286 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> d;
287 divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>*>(0), x, static_cast<limb_type>(val), d);
292 return default_ops::eval_integer_modulus(x, val);
296 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
297 BOOST_MP_FORCEINLINE typename enable_if_c<is_signed<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type
298 eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
300 return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val));
303 inline limb_type integer_gcd_reduce(limb_type u, limb_type v)
312 v >>= boost::multiprecision::detail::find_lsb(v);
317 inline double_limb_type integer_gcd_reduce(double_limb_type u, double_limb_type v)
325 if(v <= ~static_cast<limb_type>(0))
327 u = integer_gcd_reduce(static_cast<limb_type>(v), static_cast<limb_type>(u));
331 #ifdef __MSVC_RUNTIME_CHECKS
334 while((static_cast<unsigned>(v) & 1u) == 0)
341 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
342 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
344 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
345 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
348 using default_ops::eval_lsb;
349 using default_ops::eval_is_zero;
350 using default_ops::eval_get_sign;
354 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a);
356 int s = eval_get_sign(u);
374 /* Let shift := lg K, where K is the greatest power of 2
375 dividing both u and v. */
377 unsigned us = eval_lsb(u);
378 unsigned vs = boost::multiprecision::detail::find_lsb(v);
379 shift = (std::min)(us, vs);
380 eval_right_shift(u, us);
386 /* Now u and v are both odd, so diff(u, v) is even.
387 Let u = min(u, v), v = diff(u, v)/2. */
391 v = integer_gcd_reduce(*u.limbs(), v);
395 i = u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
396 v = static_cast<limb_type>(integer_gcd_reduce(i, static_cast<double_limb_type>(v)));
402 eval_right_shift(u, us);
407 eval_left_shift(result, shift);
409 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
410 inline typename enable_if_c<is_unsigned<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
412 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
413 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
416 eval_gcd(result, a, static_cast<limb_type>(v));
418 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer>
419 inline typename enable_if_c<is_signed<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
421 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
422 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
425 eval_gcd(result, a, static_cast<limb_type>(v < 0 ? -v : v));
428 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
429 inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
431 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
432 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
433 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b)
435 using default_ops::eval_lsb;
436 using default_ops::eval_is_zero;
437 using default_ops::eval_get_sign;
441 eval_gcd(result, b, *a.limbs());
446 eval_gcd(result, a, *b.limbs());
452 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a), v(b);
454 int s = eval_get_sign(u);
466 s = eval_get_sign(v);
477 /* Let shift := lg K, where K is the greatest power of 2
478 dividing both u and v. */
480 unsigned us = eval_lsb(u);
481 unsigned vs = eval_lsb(v);
482 shift = (std::min)(us, vs);
483 eval_right_shift(u, us);
484 eval_right_shift(v, vs);
488 /* Now u and v are both odd, so diff(u, v) is even.
489 Let u = min(u, v), v = diff(u, v)/2. */
498 u = integer_gcd_reduce(*v.limbs(), *u.limbs());
501 double_limb_type i, j;
502 i = v.limbs()[0] | (static_cast<double_limb_type>(v.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
503 j = (u.size() == 1) ? *u.limbs() : u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT);
504 u = integer_gcd_reduce(i, j);
510 eval_right_shift(v, vs);
515 eval_left_shift(result, shift);
518 // Now again for trivial backends:
520 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
521 BOOST_MP_FORCEINLINE typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
522 eval_gcd(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_NOEXCEPT
524 *result.limbs() = boost::integer::gcd(*a.limbs(), *b.limbs());
526 // This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version:
527 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
528 BOOST_MP_FORCEINLINE typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (Checked1 == unchecked)>::type
529 eval_lcm(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
531 *result.limbs() = boost::integer::lcm(*a.limbs(), *b.limbs());
532 result.normalize(); // result may overflow the specified number of bits
535 inline void conversion_overflow(const mpl::int_<checked>&)
537 BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type"));
539 inline void conversion_overflow(const mpl::int_<unchecked>&){}
541 template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
542 inline typename enable_if_c<
543 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
544 && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
545 && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value
547 eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
549 typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;
550 if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
554 if(static_cast<common_type>(*val.limbs()) > -static_cast<common_type>((std::numeric_limits<R>::min)()))
555 conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
556 *result = (std::numeric_limits<R>::min)();
560 conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
561 *result = (std::numeric_limits<R>::max)();
566 *result = static_cast<R>(*val.limbs());
569 check_is_negative(mpl::bool_<is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point)>());
570 *result = negate_integer(*result, mpl::bool_<is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point)>());
575 template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
576 inline typename enable_if_c<
577 is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
578 && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
579 && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value
581 eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
583 typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type;
584 if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
586 conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
587 *result = (std::numeric_limits<R>::max)();
590 *result = static_cast<R>(*val.limbs());
593 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
594 inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
595 eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
597 using default_ops::eval_get_sign;
598 if(eval_get_sign(a) == 0)
600 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
604 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
607 // Find the index of the least significant bit within that limb:
609 return boost::multiprecision::detail::find_lsb(*a.limbs());
612 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
613 inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
614 eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
617 // Find the index of the least significant bit within that limb:
619 return boost::multiprecision::detail::find_msb(*a.limbs());
622 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
623 inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type
624 eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
626 using default_ops::eval_get_sign;
627 if(eval_get_sign(a) == 0)
629 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
633 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
635 return eval_msb_imp(a);
638 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
639 inline std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
641 std::size_t result = 0;
642 for(unsigned i = 0; i < val.size(); ++i)
644 boost::hash_combine(result, val.limbs()[i]);
646 boost::hash_combine(result, val.sign());