Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:13

0001 
0002 //  Copyright 2012 John Maddock. Distributed under the Boost
0003 //  Software License, Version 1.0. (See accompanying file
0004 //  LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
0005 
0006 #ifndef BOOST_MP_CPP_INT_CHECKED_HPP
0007 #define BOOST_MP_CPP_INT_CHECKED_HPP
0008 
0009 #include <climits>
0010 #include <limits>
0011 #include <type_traits>
0012 #include <stdexcept>
0013 #include <string>
0014 #include <boost/multiprecision/detail/standalone_config.hpp>
0015 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
0016 
0017 namespace boost { namespace multiprecision { namespace backends { namespace detail {
0018 
0019 //
0020 // Simple routines for performing checked arithmetic with a builtin arithmetic type.
0021 // Note that this is not a complete header, it must be included as part of boost/multiprecision/cpp_int.hpp.
0022 //
0023 
0024 template <typename T>
0025 inline constexpr T type_max() noexcept
0026 {
0027    return 
0028    #ifdef BOOST_HAS_INT128
0029    std::is_same<T, boost::multiprecision::int128_type>::value ? INT128_MAX :
0030    std::is_same<T, boost::multiprecision::uint128_type>::value ? UINT128_MAX :
0031    #endif
0032    (std::numeric_limits<T>::max)();
0033 }
0034 
0035 template <typename T>
0036 inline constexpr T type_min() noexcept
0037 {
0038    return 
0039    #ifdef BOOST_HAS_INT128
0040    std::is_same<T, boost::multiprecision::int128_type>::value ? INT128_MIN :
0041    std::is_same<T, boost::multiprecision::uint128_type>::value ? T(0) :
0042    #endif
0043    (std::numeric_limits<T>::min)();
0044 }
0045 
0046 inline void raise_overflow(std::string op)
0047 {
0048    BOOST_MP_THROW_EXCEPTION(std::overflow_error("overflow in " + op));
0049 }
0050 inline void raise_add_overflow()
0051 {
0052    raise_overflow("addition");
0053 }
0054 inline void raise_subtract_overflow()
0055 {
0056    BOOST_MP_THROW_EXCEPTION(std::range_error("Subtraction resulted in a negative value, but the type is unsigned"));
0057 }
0058 inline void raise_mul_overflow()
0059 {
0060    raise_overflow("multiplication");
0061 }
0062 inline void raise_div_overflow()
0063 {
0064    raise_overflow("division");
0065 }
0066 
0067 template <class A>
0068 inline BOOST_MP_CXX14_CONSTEXPR A checked_add_imp(A a, A b, const std::integral_constant<bool, true>&)
0069 {
0070    if (a > 0)
0071    {
0072       if ((b > 0) && ((type_max<A>() - b) < a))
0073          raise_add_overflow();
0074    }
0075    else
0076    {
0077       if ((b < 0) && ((type_min<A>() - b) > a))
0078          raise_add_overflow();
0079    }
0080    return a + b;
0081 }
0082 template <class A>
0083 inline BOOST_MP_CXX14_CONSTEXPR A checked_add_imp(A a, A b, const std::integral_constant<bool, false>&)
0084 {
0085    if ((type_max<A>() - b) < a)
0086       raise_add_overflow();
0087    return a + b;
0088 }
0089 template <class A>
0090 inline BOOST_MP_CXX14_CONSTEXPR A checked_add(A a, A b, const std::integral_constant<int, checked>&)
0091 {
0092    return checked_add_imp(a, b, std::integral_constant<bool, boost::multiprecision::detail::is_signed<A>::value && boost::multiprecision::detail::is_integral<A>::value > ());
0093 }
0094 template <class A>
0095 inline BOOST_MP_CXX14_CONSTEXPR A checked_add(A a, A b, const std::integral_constant<int, unchecked>&)
0096 {
0097    return a + b;
0098 }
0099 
0100 template <class A>
0101 inline BOOST_MP_CXX14_CONSTEXPR A checked_subtract_imp(A a, A b, const std::integral_constant<bool, true>&)
0102 {
0103    if (a > 0)
0104    {
0105       if ((b < 0) && ((type_max<A>() + b) < a))
0106          raise_subtract_overflow();
0107    }
0108    else
0109    {
0110       if ((b > 0) && ((type_min<A>() + b) > a))
0111          raise_subtract_overflow();
0112    }
0113    return a - b;
0114 }
0115 template <class A>
0116 inline BOOST_MP_CXX14_CONSTEXPR A checked_subtract_imp(A a, A b, const std::integral_constant<bool, false>&)
0117 {
0118    if (a < b)
0119       raise_subtract_overflow();
0120    return a - b;
0121 }
0122 template <class A>
0123 inline BOOST_MP_CXX14_CONSTEXPR A checked_subtract(A a, A b, const std::integral_constant<int, checked>&)
0124 {
0125    return checked_subtract_imp(a, b, std::integral_constant<bool, boost::multiprecision::detail::is_signed<A>::value && boost::multiprecision::detail::is_integral<A>::value>());
0126 }
0127 template <class A>
0128 inline BOOST_MP_CXX14_CONSTEXPR A checked_subtract(A a, A b, const std::integral_constant<int, unchecked>&)
0129 {
0130    return a - b;
0131 }
0132 
0133 template <class A>
0134 inline BOOST_MP_CXX14_CONSTEXPR A checked_multiply(A a, A b, const std::integral_constant<int, checked>&)
0135 {
0136    BOOST_MP_USING_ABS
0137    if (a && (type_max<A>() / abs(a) < abs(b)))
0138       raise_mul_overflow();
0139    return a * b;
0140 }
0141 template <class A>
0142 inline BOOST_MP_CXX14_CONSTEXPR A checked_multiply(A a, A b, const std::integral_constant<int, unchecked>&)
0143 {
0144    return a * b;
0145 }
0146 
0147 template <class A>
0148 inline BOOST_MP_CXX14_CONSTEXPR A checked_divide(A a, A b, const std::integral_constant<int, checked>&)
0149 {
0150    if (b == 0)
0151       raise_div_overflow();
0152    return a / b;
0153 }
0154 template <class A>
0155 inline BOOST_MP_CXX14_CONSTEXPR A checked_divide(A a, A b, const std::integral_constant<int, unchecked>&)
0156 {
0157    return a / b;
0158 }
0159 
0160 template <class A>
0161 inline BOOST_MP_CXX14_CONSTEXPR A checked_left_shift(A a, unsigned long long shift, const std::integral_constant<int, checked>&)
0162 {
0163    if (a && shift)
0164    {
0165       if ((shift > sizeof(A) * CHAR_BIT) || (a >> (sizeof(A) * CHAR_BIT - shift)))
0166          BOOST_MP_THROW_EXCEPTION(std::overflow_error("Shift out of range"));
0167    }
0168    return a << shift;
0169 }
0170 template <class A>
0171 inline BOOST_MP_CXX14_CONSTEXPR A checked_left_shift(A a, unsigned long long shift, const std::integral_constant<int, unchecked>&)
0172 {
0173    return (shift >= sizeof(A) * CHAR_BIT) ? 0 : a << shift;
0174 }
0175 
0176 }}}} // namespace boost::multiprecision::backends::detail
0177 
0178 #endif