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_COMPARISON_HPP
9 #define BOOST_MP_CPP_INT_COMPARISON_HPP
11 #include <boost/type_traits/make_unsigned.hpp>
13 namespace boost{ namespace multiprecision{ namespace backends{
17 #pragma warning(disable:4018 4389 4996)
21 // Start with non-trivial cpp_int's:
23 template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator>
24 BOOST_MP_FORCEINLINE typename enable_if_c<
25 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value,
28 eval_eq(const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& a, const cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& b) BOOST_NOEXCEPT
30 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
31 return (a.sign() == b.sign())
32 && (a.size() == b.size())
33 && std::equal(a.limbs(), a.limbs() + a.size(),
34 stdext::checked_array_iterator<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::const_limb_pointer>(b.limbs(), b.size()));
36 return (a.sign() == b.sign())
37 && (a.size() == b.size())
38 && std::equal(a.limbs(), a.limbs() + a.size(), b.limbs());
41 template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
42 BOOST_MP_FORCEINLINE typename enable_if_c<
43 !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
44 && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value,
47 eval_eq(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& b) BOOST_NOEXCEPT
49 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600)
50 return (a.sign() == b.sign())
51 && (a.size() == b.size())
52 && std::equal(a.limbs(), a.limbs() + a.size(), stdext::checked_array_iterator<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>::const_limb_pointer>(b.limbs(), b.size()));
54 return (a.sign() == b.sign())
55 && (a.size() == b.size())
56 && std::equal(a.limbs(), a.limbs() + a.size(), b.limbs());
59 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
60 BOOST_MP_FORCEINLINE typename enable_if_c<
61 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
63 >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
65 return (a.sign() == false)
69 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
70 BOOST_MP_FORCEINLINE typename enable_if_c<
71 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
73 >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
75 return (a.sign() == (b < 0))
77 && (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b));
79 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
80 BOOST_MP_FORCEINLINE typename enable_if_c<
81 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
83 >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
85 return (a.size() == 1)
88 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
89 BOOST_MP_FORCEINLINE typename enable_if_c<
90 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
92 >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
94 return (b < 0) ? eval_eq(a, cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>(b)) : eval_eq(a, static_cast<limb_type>(b)); // Use bit pattern of b for comparison
97 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
98 BOOST_MP_FORCEINLINE typename enable_if_c<
99 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
101 >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
107 return *a.limbs() < b;
109 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
110 inline typename enable_if_c<
111 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
113 >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
115 if((b == 0) || (a.sign() != (b < 0)))
121 return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b);
127 return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b);
131 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
132 BOOST_MP_FORCEINLINE typename enable_if_c<
133 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
135 >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
139 return *a.limbs() < b;
141 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
142 BOOST_MP_FORCEINLINE typename enable_if_c<
143 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
145 >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
147 return (b < 0) ? a.compare(b) < 0 : eval_lt(a, static_cast<limb_type>(b)); // Use bit pattern of b for comparison
150 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
151 BOOST_MP_FORCEINLINE typename enable_if_c<
152 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator> >::value,
154 >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
160 return *a.limbs() > b;
162 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
163 inline typename enable_if_c<
164 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
166 >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
169 return !a.sign() && ((a.size() > 1) || *a.limbs());
170 if(a.sign() != (b < 0))
176 return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b);
182 return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b);
186 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
187 BOOST_MP_FORCEINLINE typename enable_if_c<
188 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
190 >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, limb_type b) BOOST_NOEXCEPT
194 return *a.limbs() > b;
196 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class Allocator>
197 BOOST_MP_FORCEINLINE typename enable_if_c<
198 !is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator> >::value,
200 >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, Allocator>& a, signed_limb_type b) BOOST_NOEXCEPT
202 return (b < 0) ? a.compare(b) > 0 : eval_gt(a, static_cast<limb_type>(b)); // Use bit pattern of b for comparison.
205 // And again for trivial cpp_ints:
207 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
208 BOOST_MP_FORCEINLINE typename enable_if_c<
209 is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
211 >::value eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& b) BOOST_NOEXCEPT
213 return (a.sign() == b.sign()) && (*a.limbs() == *b.limbs());
215 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
216 BOOST_MP_FORCEINLINE typename enable_if_c<
217 is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
219 >::value eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) BOOST_NOEXCEPT
221 return *a.limbs() == *b.limbs();
223 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
224 BOOST_MP_FORCEINLINE typename enable_if_c<
225 is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
227 >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
229 return !a.sign() && (*a.limbs() == b);
231 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
232 BOOST_MP_FORCEINLINE typename enable_if_c<
233 is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
235 >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
237 return (a.sign() == (b < 0)) && (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b));
239 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
240 BOOST_MP_FORCEINLINE typename enable_if_c<
241 is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
243 >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
245 return *a.limbs() == b;
247 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
248 BOOST_MP_FORCEINLINE typename enable_if_c<
249 is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
251 >::type eval_eq(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
253 typedef typename make_unsigned<S>::type ui_type;
256 cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> t(b);
257 return *a.limbs() == *t.limbs();
261 return *a.limbs() == static_cast<ui_type>(b);
265 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
266 BOOST_MP_FORCEINLINE typename enable_if_c<
267 is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
269 >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) BOOST_NOEXCEPT
271 if(a.sign() != b.sign())
273 return a.sign() ? *a.limbs() > *b.limbs() : *a.limbs() < *b.limbs();
275 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
276 BOOST_MP_FORCEINLINE typename enable_if_c<
277 is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
279 >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) BOOST_NOEXCEPT
281 return *a.limbs() < *b.limbs();
283 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
284 BOOST_MP_FORCEINLINE typename enable_if_c<
285 is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
287 >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
291 return *a.limbs() < b;
293 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
294 BOOST_MP_FORCEINLINE typename enable_if_c<
295 is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
297 >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
299 if(a.sign() != (b < 0))
301 return a.sign() ? (*a.limbs() > boost::multiprecision::detail::unsigned_abs(b)) : (*a.limbs() < boost::multiprecision::detail::unsigned_abs(b));
303 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
304 BOOST_MP_FORCEINLINE typename enable_if_c<
305 is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
307 >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
309 return *a.limbs() < b;
311 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
312 BOOST_MP_FORCEINLINE typename enable_if_c<
313 is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
315 >::type eval_lt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
317 typedef typename make_unsigned<S>::type ui_type;
320 cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> t(b);
321 return *a.limbs() < *t.limbs();
325 return *a.limbs() < static_cast<ui_type>(b);
329 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
330 BOOST_MP_FORCEINLINE typename enable_if_c<
331 is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
333 >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& b) BOOST_NOEXCEPT
335 if(a.sign() != b.sign())
337 return a.sign() ? *a.limbs() < *b.limbs() : *a.limbs() > *b.limbs();
339 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked>
340 BOOST_MP_FORCEINLINE typename enable_if_c<
341 is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
343 >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& b) BOOST_NOEXCEPT
345 return *a.limbs() > *b.limbs();
347 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
348 BOOST_MP_FORCEINLINE typename enable_if_c<
349 is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
351 >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
355 return *a.limbs() > b;
357 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
358 BOOST_MP_FORCEINLINE typename enable_if_c<
359 is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void> >::value,
361 >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, signed_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
363 if(a.sign() != (b < 0))
365 return a.sign() ? (*a.limbs() < boost::multiprecision::detail::unsigned_abs(b)) : (*a.limbs() > boost::multiprecision::detail::unsigned_abs(b));
367 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class U>
368 BOOST_MP_FORCEINLINE typename enable_if_c<
369 is_unsigned<U>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
371 >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, U b) BOOST_NOEXCEPT
373 return *a.limbs() > b;
375 template <unsigned MinBits, unsigned MaxBits, cpp_int_check_type Checked, class S>
376 BOOST_MP_FORCEINLINE typename enable_if_c<
377 is_signed<S>::value && is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> >::value,
379 >::type eval_gt(const cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void>& a, S b) BOOST_NOEXCEPT
381 typedef typename make_unsigned<S>::type ui_type;
384 cpp_int_backend<MinBits, MaxBits, unsigned_magnitude, Checked, void> t(b);
385 return *a.limbs() > *t.limbs();
389 return *a.limbs() > static_cast<ui_type>(b);