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_
5 //
6 // Comparison operators for cpp_int_backend:
7 //
8 #ifndef BOOST_MP_CPP_INT_MISC_HPP
9 #define BOOST_MP_CPP_INT_MISC_HPP
10 
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>
14 
15 #ifdef BOOST_MSVC
16 #pragma warning(push)
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
20 #endif
21 
22 
23 namespace boost{ namespace multiprecision{ namespace backends{
24 
25 template <class R, class CppInt>
check_in_range(const CppInt & val,const mpl::int_<checked> &)26 void check_in_range(const CppInt& val, const mpl::int_<checked>&)
27 {
28    typedef typename boost::multiprecision::detail::canonical<R, CppInt>::type cast_type;
29    if(val.sign())
30    {
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."));
33    }
34    else
35    {
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."));
38    }
39 }
40 template <class R, class CppInt>
check_in_range(const CppInt &,const mpl::int_<unchecked> &)41 inline void check_in_range(const CppInt& /*val*/, const mpl::int_<unchecked>&) BOOST_NOEXCEPT {}
42 
check_is_negative(const mpl::true_ &)43 inline void check_is_negative(const mpl::true_&) BOOST_NOEXCEPT {}
check_is_negative(const mpl::false_ &)44 inline void check_is_negative(const mpl::false_&)
45 {
46    BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type."));
47 }
48 
49 template <class Integer>
negate_integer(Integer i,const mpl::true_ &)50 inline Integer negate_integer(Integer i, const mpl::true_&) BOOST_NOEXCEPT
51 {
52    return -i;
53 }
54 template <class Integer>
negate_integer(Integer i,const mpl::false_ &)55 inline Integer negate_integer(Integer i, const mpl::false_&) BOOST_NOEXCEPT
56 {
57    return ~(i-1);
58 }
59 
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
eval_convert_to(R * result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & backend)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))
63 {
64    typedef mpl::int_<Checked1> checked_type;
65    check_in_range<R>(backend, checked_type());
66 
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)
70    {
71       *result += static_cast<R>(backend.limbs()[i]) << shift;
72       shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
73    }
74    if(backend.sign())
75    {
76       check_is_negative(boost::is_signed<R>());
77       *result = negate_integer(*result, boost::is_signed<R>());
78    }
79 }
80 
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
eval_convert_to(R * result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & backend)83    eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) BOOST_MP_NOEXCEPT_IF(is_arithmetic<R>::value)
84 {
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)
89    {
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;
92    }
93    if(backend.sign())
94       *result = -*result;
95 }
96 
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
eval_is_zero(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & val)99    eval_is_zero(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
100 {
101    return (val.size() == 1) && (val.limbs()[0] == 0);
102 }
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
eval_get_sign(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & val)105    eval_get_sign(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
106 {
107    return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1;
108 }
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
eval_abs(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & val)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))
112 {
113    result = val;
114    result.sign(false);
115 }
116 
117 //
118 // Get the location of the least-significant-bit:
119 //
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
eval_lsb(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & a)122    eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
123 {
124    using default_ops::eval_get_sign;
125    if(eval_get_sign(a) == 0)
126    {
127       BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
128    }
129    if(a.sign())
130    {
131       BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
132    }
133 
134    //
135    // Find the index of the least significant limb that is non-zero:
136    //
137    unsigned index = 0;
138    while(!a.limbs()[index] && (index < a.size()))
139       ++index;
140    //
141    // Find the index of the least significant bit within that limb:
142    //
143    unsigned result = boost::multiprecision::detail::find_lsb(a.limbs()[index]);
144 
145    return result + index * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits;
146 }
147 
148 //
149 // Get the location of the most-significant-bit:
150 //
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
eval_msb_imp(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & a)153 eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
154 {
155    //
156    // Find the index of the most significant bit that is non-zero:
157    //
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]);
159 }
160 
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
eval_msb(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & a)163    eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
164 {
165    using default_ops::eval_get_sign;
166    if(eval_get_sign(a) == 0)
167    {
168       BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
169    }
170    if(a.sign())
171    {
172       BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
173    }
174    return eval_msb_imp(a);
175 }
176 
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
eval_bit_test(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & val,unsigned index)179    eval_bit_test(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT
180 {
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())
185       return false;
186    return val.limbs()[offset] & mask ? true : false;
187 }
188 
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
eval_bit_set(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & val,unsigned index)191    eval_bit_set(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index)
192 {
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())
197    {
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)
203          val.limbs()[i] = 0;
204    }
205    val.limbs()[offset] |= mask;
206 }
207 
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
eval_bit_unset(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & val,unsigned index)210    eval_bit_unset(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT
211 {
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())
216       return;
217    val.limbs()[offset] &= ~mask;
218    val.normalize();
219 }
220 
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
eval_bit_flip(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & val,unsigned index)223    eval_bit_flip(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index)
224 {
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())
229    {
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)
235          val.limbs()[i] = 0;
236    }
237    val.limbs()[offset] ^= mask;
238    val.normalize();
239 }
240 
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
eval_qr(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & x,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & y,cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & q,cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & r)243    eval_qr(
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))
248 {
249    divide_unsigned_helper(&q, x, y, r);
250    q.sign(x.sign() != y.sign());
251    r.sign(x.sign());
252 }
253 
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
eval_qr(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & x,limb_type y,cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & q,cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & r)256    eval_qr(
257       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
258       limb_type y,
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))
261 {
262    divide_unsigned_helper(&q, x, y, r);
263    q.sign(x.sign());
264    r.sign(x.sign());
265 }
266 
267 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class U>
eval_qr(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & x,U y,cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & q,cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & r)268 inline typename enable_if_c<is_integral<U>::value>::type eval_qr(
269       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x,
270       U y,
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))
273 {
274    using default_ops::eval_qr;
275    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t;
276    t = y;
277    eval_qr(x, t, q, r);
278 }
279 
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
eval_integer_modulus(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & x,Integer val)282    eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
283 {
284    if((sizeof(Integer) <= sizeof(limb_type)) || (val <= (std::numeric_limits<limb_type>::max)()))
285    {
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);
288       return d.limbs()[0];
289    }
290    else
291    {
292       return default_ops::eval_integer_modulus(x, val);
293    }
294 }
295 
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
eval_integer_modulus(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & x,Integer val)298    eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val)
299 {
300    return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val));
301 }
302 
integer_gcd_reduce(limb_type u,limb_type v)303 inline limb_type integer_gcd_reduce(limb_type u, limb_type v)
304 {
305    do
306    {
307       if(u > v)
308          std::swap(u, v);
309       if(u == v)
310          break;
311       v -= u;
312       v >>= boost::multiprecision::detail::find_lsb(v);
313    } while(true);
314    return u;
315 }
316 
integer_gcd_reduce(double_limb_type u,double_limb_type v)317 inline double_limb_type integer_gcd_reduce(double_limb_type u, double_limb_type v)
318 {
319    do
320    {
321       if(u > v)
322          std::swap(u, v);
323       if(u == v)
324          break;
325       if(v <= ~static_cast<limb_type>(0))
326       {
327          u = integer_gcd_reduce(static_cast<limb_type>(v), static_cast<limb_type>(u));
328          break;
329       }
330       v -= u;
331 #ifdef __MSVC_RUNTIME_CHECKS
332       while((v & 1u) == 0)
333 #else
334       while((static_cast<unsigned>(v) & 1u) == 0)
335 #endif
336          v >>= 1;
337    } while(true);
338    return u;
339 }
340 
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
eval_gcd(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & a,limb_type v)343    eval_gcd(
344       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
345       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
346       limb_type v)
347 {
348    using default_ops::eval_lsb;
349    using default_ops::eval_is_zero;
350    using default_ops::eval_get_sign;
351 
352    int shift;
353 
354    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a);
355 
356    int s = eval_get_sign(u);
357 
358    /* GCD(0,x) := x */
359    if(s < 0)
360    {
361       u.negate();
362    }
363    else if(s == 0)
364    {
365       result = v;
366       return;
367    }
368    if(v == 0)
369    {
370       result = u;
371       return;
372    }
373 
374    /* Let shift := lg K, where K is the greatest power of 2
375    dividing both u and v. */
376 
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);
381    if(vs)
382       v >>= vs;
383 
384    do
385    {
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. */
388       if(u.size() <= 2)
389       {
390          if(u.size() == 1)
391             v = integer_gcd_reduce(*u.limbs(), v);
392          else
393          {
394             double_limb_type i;
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)));
397          }
398          break;
399       }
400       eval_subtract(u, v);
401       us = eval_lsb(u);
402       eval_right_shift(u, us);
403    }
404    while(true);
405 
406    result = v;
407    eval_left_shift(result, shift);
408 }
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
eval_gcd(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & a,const Integer & v)411    eval_gcd(
412       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
413       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
414       const Integer& v)
415 {
416    eval_gcd(result, a, static_cast<limb_type>(v));
417 }
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
eval_gcd(cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & a,const Integer & v)420    eval_gcd(
421       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
422       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,
423       const Integer& v)
424 {
425    eval_gcd(result, a, static_cast<limb_type>(v < 0 ? -v : v));
426 }
427 
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
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)430    eval_gcd(
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)
434 {
435    using default_ops::eval_lsb;
436    using default_ops::eval_is_zero;
437    using default_ops::eval_get_sign;
438 
439    if(a.size() == 1)
440    {
441       eval_gcd(result, b, *a.limbs());
442       return;
443    }
444    if(b.size() == 1)
445    {
446       eval_gcd(result, a, *b.limbs());
447       return;
448    }
449 
450    int shift;
451 
452    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a), v(b);
453 
454    int s = eval_get_sign(u);
455 
456    /* GCD(0,x) := x */
457    if(s < 0)
458    {
459       u.negate();
460    }
461    else if(s == 0)
462    {
463       result = v;
464       return;
465    }
466    s = eval_get_sign(v);
467    if(s < 0)
468    {
469       v.negate();
470    }
471    else if(s == 0)
472    {
473       result = u;
474       return;
475    }
476 
477    /* Let shift := lg K, where K is the greatest power of 2
478    dividing both u and v. */
479 
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);
485 
486    do
487    {
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. */
490       s = u.compare(v);
491       if(s > 0)
492          u.swap(v);
493       if(s == 0)
494          break;
495       if(v.size() <= 2)
496       {
497          if(v.size() == 1)
498             u = integer_gcd_reduce(*v.limbs(), *u.limbs());
499          else
500          {
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);
505          }
506          break;
507       }
508       eval_subtract(v, u);
509       vs = eval_lsb(v);
510       eval_right_shift(v, vs);
511    }
512    while(true);
513 
514    result = u;
515    eval_left_shift(result, shift);
516 }
517 //
518 // Now again for trivial backends:
519 //
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
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)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
523 {
524    *result.limbs() = boost::integer::gcd(*a.limbs(), *b.limbs());
525 }
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
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)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))
530 {
531    *result.limbs() = boost::integer::lcm(*a.limbs(), *b.limbs());
532    result.normalize(); // result may overflow the specified number of bits
533 }
534 
conversion_overflow(const mpl::int_<checked> &)535 inline void conversion_overflow(const mpl::int_<checked>&)
536 {
537    BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type"));
538 }
conversion_overflow(const mpl::int_<unchecked> &)539 inline void conversion_overflow(const mpl::int_<unchecked>&){}
540 
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
546          >::type
eval_convert_to(R * result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & val)547    eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
548 {
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)())))
551    {
552       if(val.isneg())
553       {
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)();
557       }
558       else
559       {
560          conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
561          *result = (std::numeric_limits<R>::max)();
562       }
563    }
564    else
565    {
566       *result = static_cast<R>(*val.limbs());
567       if(val.isneg())
568       {
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)>());
571       }
572    }
573 }
574 
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
580          >::type
eval_convert_to(R * result,const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & val)581    eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
582 {
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)())))
585    {
586       conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
587       *result = (std::numeric_limits<R>::max)();
588    }
589    else
590       *result = static_cast<R>(*val.limbs());
591 }
592 
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
eval_lsb(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & a)595    eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
596 {
597    using default_ops::eval_get_sign;
598    if(eval_get_sign(a) == 0)
599    {
600       BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
601    }
602    if(a.sign())
603    {
604       BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
605    }
606    //
607    // Find the index of the least significant bit within that limb:
608    //
609    return boost::multiprecision::detail::find_lsb(*a.limbs());
610 }
611 
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
eval_msb_imp(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & a)614 eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
615 {
616    //
617    // Find the index of the least significant bit within that limb:
618    //
619    return boost::multiprecision::detail::find_msb(*a.limbs());
620 }
621 
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
eval_msb(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & a)624    eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a)
625 {
626    using default_ops::eval_get_sign;
627    if(eval_get_sign(a) == 0)
628    {
629       BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
630    }
631    if(a.sign())
632    {
633       BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
634    }
635    return eval_msb_imp(a);
636 }
637 
638 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
hash_value(const cpp_int_backend<MinBits1,MaxBits1,SignType1,Checked1,Allocator1> & val)639 inline std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT
640 {
641    std::size_t result = 0;
642    for(unsigned i = 0; i < val.size(); ++i)
643    {
644       boost::hash_combine(result, val.limbs()[i]);
645    }
646    boost::hash_combine(result, val.sign());
647    return result;
648 }
649 
650 #ifdef BOOST_MSVC
651 #pragma warning(pop)
652 #endif
653 
654 }}} // namespaces
655 
656 #endif
657