Chris@16: /////////////////////////////////////////////////////////////// Chris@16: // Copyright 2012 John Maddock. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ Chris@16: // Chris@16: // Comparison operators for cpp_int_backend: Chris@16: // Chris@16: #ifndef BOOST_MP_CPP_INT_COMPARISON_HPP Chris@16: #define BOOST_MP_CPP_INT_COMPARISON_HPP Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost{ namespace multiprecision{ namespace backends{ Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(push) Chris@16: #pragma warning(disable:4018 4389 4996) Chris@16: #endif Chris@16: Chris@16: // Chris@16: // Start with non-trivial cpp_int's: Chris@16: // Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type Chris@16: eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT Chris@16: { Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) Chris@16: return (a.sign() == b.sign()) Chris@16: && (a.size() == b.size()) Chris@16: && std::equal(a.limbs(), a.limbs() + a.size(), Chris@16: stdext::checked_array_iterator::const_limb_pointer>(b.limbs(), b.size())); Chris@16: #else Chris@16: return (a.sign() == b.sign()) Chris@16: && (a.size() == b.size()) Chris@16: && std::equal(a.limbs(), a.limbs() + a.size(), b.limbs()); Chris@16: #endif Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value Chris@16: && !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type Chris@16: eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT Chris@16: { Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, >= 1600) Chris@16: return (a.sign() == b.sign()) Chris@16: && (a.size() == b.size()) Chris@16: && std::equal(a.limbs(), a.limbs() + a.size(), stdext::checked_array_iterator::const_limb_pointer>(b.limbs(), b.size())); Chris@16: #else Chris@16: return (a.sign() == b.sign()) Chris@16: && (a.size() == b.size()) Chris@16: && std::equal(a.limbs(), a.limbs() + a.size(), b.limbs()); Chris@16: #endif Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_eq(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: return (a.sign() == false) Chris@16: && (a.size() == 1) Chris@16: && (*a.limbs() == b); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_eq(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: return (a.sign() == (b < 0)) Chris@16: && (a.size() == 1) Chris@101: && (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b)); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_eq(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: return (a.size() == 1) Chris@16: && (*a.limbs() == b); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_eq(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: return (b < 0) ? eval_eq(a, cpp_int_backend(b)) : eval_eq(a, static_cast(b)); // Use bit pattern of b for comparison Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_lt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: if(a.sign()) Chris@16: return true; Chris@16: if(a.size() > 1) Chris@16: return false; Chris@16: return *a.limbs() < b; Chris@16: } Chris@16: template Chris@16: inline typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_lt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: if((b == 0) || (a.sign() != (b < 0))) Chris@16: return a.sign(); Chris@16: if(a.sign()) Chris@16: { Chris@16: if(a.size() > 1) Chris@16: return true; Chris@101: return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b); Chris@16: } Chris@16: else Chris@16: { Chris@16: if(a.size() > 1) Chris@16: return false; Chris@101: return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_lt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: if(a.size() > 1) Chris@16: return false; Chris@16: return *a.limbs() < b; Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_lt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: return (b < 0) ? a.compare(b) < 0 : eval_lt(a, static_cast(b)); // Use bit pattern of b for comparison Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_gt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: if(a.sign()) Chris@16: return false; Chris@16: if(a.size() > 1) Chris@16: return true; Chris@16: return *a.limbs() > b; Chris@16: } Chris@16: template Chris@16: inline typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_gt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: if(b == 0) Chris@16: return !a.sign() && ((a.size() > 1) || *a.limbs()); Chris@16: if(a.sign() != (b < 0)) Chris@16: return !a.sign(); Chris@16: if(a.sign()) Chris@16: { Chris@16: if(a.size() > 1) Chris@16: return false; Chris@101: return *a.limbs() < boost::multiprecision::detail::unsigned_abs(b); Chris@16: } Chris@16: else Chris@16: { Chris@16: if(a.size() > 1) Chris@16: return true; Chris@101: return *a.limbs() > boost::multiprecision::detail::unsigned_abs(b); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_gt(const cpp_int_backend& a, limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: if(a.size() > 1) Chris@16: return true; Chris@16: return *a.limbs() > b; Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: !is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_gt(const cpp_int_backend& a, signed_limb_type b) BOOST_NOEXCEPT Chris@16: { Chris@16: return (b < 0) ? a.compare(b) > 0 : eval_gt(a, static_cast(b)); // Use bit pattern of b for comparison. Chris@16: } Chris@16: // Chris@16: // And again for trivial cpp_ints: Chris@16: // Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::value eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT Chris@16: { Chris@16: return (a.sign() == b.sign()) && (*a.limbs() == *b.limbs()); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::value eval_eq(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT Chris@16: { Chris@16: return *a.limbs() == *b.limbs(); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_unsigned::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_eq(const cpp_int_backend& a, U b) BOOST_NOEXCEPT Chris@16: { Chris@16: return !a.sign() && (*a.limbs() == b); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_signed::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_eq(const cpp_int_backend& a, S b) BOOST_NOEXCEPT Chris@16: { Chris@101: return (a.sign() == (b < 0)) && (*a.limbs() == boost::multiprecision::detail::unsigned_abs(b)); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_unsigned::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_eq(const cpp_int_backend& a, U b) BOOST_NOEXCEPT Chris@16: { Chris@16: return *a.limbs() == b; Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_signed::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_eq(const cpp_int_backend& a, S b) BOOST_NOEXCEPT Chris@16: { Chris@16: typedef typename make_unsigned::type ui_type; Chris@16: if(b < 0) Chris@16: { Chris@16: cpp_int_backend t(b); Chris@16: return *a.limbs() == *t.limbs(); Chris@16: } Chris@16: else Chris@16: { Chris@16: return *a.limbs() == static_cast(b); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_lt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT Chris@16: { Chris@16: if(a.sign() != b.sign()) Chris@16: return a.sign(); Chris@16: return a.sign() ? *a.limbs() > *b.limbs() : *a.limbs() < *b.limbs(); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_lt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT Chris@16: { Chris@16: return *a.limbs() < *b.limbs(); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_unsigned::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_lt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT Chris@16: { Chris@16: if(a.sign()) Chris@16: return true; Chris@16: return *a.limbs() < b; Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_signed::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_lt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT Chris@16: { Chris@16: if(a.sign() != (b < 0)) Chris@16: return a.sign(); Chris@101: return a.sign() ? (*a.limbs() > boost::multiprecision::detail::unsigned_abs(b)) : (*a.limbs() < boost::multiprecision::detail::unsigned_abs(b)); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_unsigned::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_lt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT Chris@16: { Chris@16: return *a.limbs() < b; Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_signed::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_lt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT Chris@16: { Chris@16: typedef typename make_unsigned::type ui_type; Chris@16: if(b < 0) Chris@16: { Chris@16: cpp_int_backend t(b); Chris@16: return *a.limbs() < *t.limbs(); Chris@16: } Chris@16: else Chris@16: { Chris@16: return *a.limbs() < static_cast(b); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_gt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT Chris@16: { Chris@16: if(a.sign() != b.sign()) Chris@16: return !a.sign(); Chris@16: return a.sign() ? *a.limbs() < *b.limbs() : *a.limbs() > *b.limbs(); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_gt(const cpp_int_backend& a, const cpp_int_backend& b) BOOST_NOEXCEPT Chris@16: { Chris@16: return *a.limbs() > *b.limbs(); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_unsigned::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_gt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT Chris@16: { Chris@16: if(a.sign()) Chris@16: return false; Chris@16: return *a.limbs() > b; Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_signed::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_gt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT Chris@16: { Chris@16: if(a.sign() != (b < 0)) Chris@16: return !a.sign(); Chris@101: return a.sign() ? (*a.limbs() < boost::multiprecision::detail::unsigned_abs(b)) : (*a.limbs() > boost::multiprecision::detail::unsigned_abs(b)); Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_unsigned::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_gt(const cpp_int_backend& a, U b) BOOST_NOEXCEPT Chris@16: { Chris@16: return *a.limbs() > b; Chris@16: } Chris@16: template Chris@16: BOOST_MP_FORCEINLINE typename enable_if_c< Chris@16: is_signed::value && is_trivial_cpp_int >::value, Chris@16: bool Chris@16: >::type eval_gt(const cpp_int_backend& a, S b) BOOST_NOEXCEPT Chris@16: { Chris@16: typedef typename make_unsigned::type ui_type; Chris@16: if(b < 0) Chris@16: { Chris@16: cpp_int_backend t(b); Chris@16: return *a.limbs() > *t.limbs(); Chris@16: } Chris@16: else Chris@16: { Chris@16: return *a.limbs() > static_cast(b); Chris@16: } Chris@16: } Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: }}} // namespaces Chris@16: Chris@16: #endif