annotate DEPENDENCIES/generic/include/boost/multiprecision/cpp_int/checked.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1
Chris@16 2 // Copyright 2012 John Maddock. Distributed under the Boost
Chris@16 3 // Software License, Version 1.0. (See accompanying file
Chris@16 4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
Chris@16 5
Chris@16 6 #ifndef BOOST_MP_CPP_INT_CHECKED_HPP
Chris@16 7 #define BOOST_MP_CPP_INT_CHECKED_HPP
Chris@16 8
Chris@16 9 namespace boost{ namespace multiprecision{ namespace backends{ namespace detail{
Chris@16 10
Chris@16 11 //
Chris@16 12 // Simple routines for performing checked arithmetic with a builtin arithmetic type.
Chris@16 13 // Note that this is not a complete header, it must be included as part of boost/multiprecision/cpp_int.hpp.
Chris@16 14 //
Chris@16 15
Chris@16 16 inline void raise_overflow(std::string op)
Chris@16 17 {
Chris@16 18 BOOST_THROW_EXCEPTION(std::overflow_error("overflow in " + op));
Chris@16 19 }
Chris@16 20 inline void raise_add_overflow()
Chris@16 21 {
Chris@16 22 raise_overflow("addition");
Chris@16 23 }
Chris@16 24 inline void raise_subtract_overflow()
Chris@16 25 {
Chris@16 26 BOOST_THROW_EXCEPTION(std::range_error("Subtraction resulted in a negative value, but the type is unsigned"));
Chris@16 27 }
Chris@16 28 inline void raise_mul_overflow()
Chris@16 29 {
Chris@16 30 raise_overflow("multiplication");
Chris@16 31 }
Chris@16 32 inline void raise_div_overflow()
Chris@16 33 {
Chris@16 34 raise_overflow("division");
Chris@16 35 }
Chris@16 36
Chris@16 37 template <class A>
Chris@16 38 inline A checked_add_imp(A a, A b, const mpl::true_&)
Chris@16 39 {
Chris@16 40 if(a > 0)
Chris@16 41 {
Chris@16 42 if((b > 0) && ((integer_traits<A>::const_max - b) < a))
Chris@16 43 raise_add_overflow();
Chris@16 44 }
Chris@16 45 else
Chris@16 46 {
Chris@16 47 if((b < 0) && ((integer_traits<A>::const_min - b) > a))
Chris@16 48 raise_add_overflow();
Chris@16 49 }
Chris@16 50 return a + b;
Chris@16 51 }
Chris@16 52 template <class A>
Chris@16 53 inline A checked_add_imp(A a, A b, const mpl::false_&)
Chris@16 54 {
Chris@16 55 if((integer_traits<A>::const_max - b) < a)
Chris@16 56 raise_add_overflow();
Chris@16 57 return a + b;
Chris@16 58 }
Chris@16 59 template <class A>
Chris@16 60 inline A checked_add(A a, A b, const mpl::int_<checked>&)
Chris@16 61 {
Chris@16 62 return checked_add_imp(a, b, boost::is_signed<A>());
Chris@16 63 }
Chris@16 64 template <class A>
Chris@16 65 inline A checked_add(A a, A b, const mpl::int_<unchecked>&)
Chris@16 66 {
Chris@16 67 return a + b;
Chris@16 68 }
Chris@16 69
Chris@16 70 template <class A>
Chris@16 71 inline A checked_subtract_imp(A a, A b, const mpl::true_&)
Chris@16 72 {
Chris@16 73 if(a > 0)
Chris@16 74 {
Chris@16 75 if((b < 0) && ((integer_traits<A>::const_max + b) < a))
Chris@16 76 raise_subtract_overflow();
Chris@16 77 }
Chris@16 78 else
Chris@16 79 {
Chris@16 80 if((b > 0) && ((integer_traits<A>::const_min + b) > a))
Chris@16 81 raise_subtract_overflow();
Chris@16 82 }
Chris@16 83 return a - b;
Chris@16 84 }
Chris@16 85 template <class A>
Chris@16 86 inline A checked_subtract_imp(A a, A b, const mpl::false_&)
Chris@16 87 {
Chris@16 88 if(a < b)
Chris@16 89 raise_subtract_overflow();
Chris@16 90 return a - b;
Chris@16 91 }
Chris@16 92 template <class A>
Chris@16 93 inline A checked_subtract(A a, A b, const mpl::int_<checked>&)
Chris@16 94 {
Chris@16 95 return checked_subtract_imp(a, b, boost::is_signed<A>());
Chris@16 96 }
Chris@16 97 template <class A>
Chris@16 98 inline A checked_subtract(A a, A b, const mpl::int_<unchecked>&)
Chris@16 99 {
Chris@16 100 return a - b;
Chris@16 101 }
Chris@16 102
Chris@16 103 template <class A>
Chris@16 104 inline A checked_multiply(A a, A b, const mpl::int_<checked>&)
Chris@16 105 {
Chris@16 106 BOOST_MP_USING_ABS
Chris@16 107 if(a && (integer_traits<A>::const_max / abs(a) < abs(b)))
Chris@16 108 raise_mul_overflow();
Chris@16 109 return a * b;
Chris@16 110 }
Chris@16 111 template <class A>
Chris@16 112 inline A checked_multiply(A a, A b, const mpl::int_<unchecked>&)
Chris@16 113 {
Chris@16 114 return a * b;
Chris@16 115 }
Chris@16 116
Chris@16 117 template <class A>
Chris@16 118 inline A checked_divide(A a, A b, const mpl::int_<checked>&)
Chris@16 119 {
Chris@16 120 if(b == 0)
Chris@16 121 raise_div_overflow();
Chris@16 122 return a / b;
Chris@16 123 }
Chris@16 124 template <class A>
Chris@16 125 inline A checked_divide(A a, A b, const mpl::int_<unchecked>&)
Chris@16 126 {
Chris@16 127 return a / b;
Chris@16 128 }
Chris@16 129
Chris@16 130 template <class A>
Chris@16 131 inline A checked_left_shift(A a, unsigned long long shift, const mpl::int_<checked>&)
Chris@16 132 {
Chris@16 133 if(a && shift)
Chris@16 134 {
Chris@16 135 if((shift > sizeof(A) * CHAR_BIT) || (a >> (sizeof(A) * CHAR_BIT - shift)))
Chris@16 136 BOOST_THROW_EXCEPTION(std::overflow_error("Shift out of range"));
Chris@16 137 }
Chris@16 138 return a << shift;
Chris@16 139 }
Chris@16 140 template <class A>
Chris@16 141 inline A checked_left_shift(A a, unsigned long long shift, const mpl::int_<unchecked>&)
Chris@16 142 {
Chris@16 143 return (shift >= sizeof(A) * CHAR_BIT) ? 0 : a << shift;
Chris@16 144 }
Chris@16 145
Chris@16 146 }}}} // namespaces
Chris@16 147
Chris@16 148 #endif
Chris@16 149