]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////// |
2 | // Copyright 2012 John Maddock. Distributed under the Boost | |
3 | // Software License, Version 1.0. (See accompanying file | |
92f5a8d4 | 4 | // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt |
7c673cae FG |
5 | // |
6 | // Comparison operators for cpp_int_backend: | |
7 | // | |
8 | #ifndef BOOST_MP_CPP_INT_ADD_HPP | |
9 | #define BOOST_MP_CPP_INT_ADD_HPP | |
10 | ||
92f5a8d4 | 11 | #include <boost/multiprecision/detail/constexpr.hpp> |
20effc67 | 12 | #include <boost/multiprecision/cpp_int/add_unsigned.hpp> |
92f5a8d4 TL |
13 | |
14 | namespace boost { namespace multiprecision { namespace backends { | |
7c673cae FG |
15 | |
16 | #ifdef _MSC_VER | |
17 | #pragma warning(push) | |
92f5a8d4 | 18 | #pragma warning(disable : 4127) // conditional expression is constant |
7c673cae FG |
19 | #endif |
20 | ||
7c673cae FG |
21 | // |
22 | // As above, but for adding a single limb to a non-trivial cpp_int: | |
23 | // | |
24 | template <class CppInt1, class CppInt2> | |
92f5a8d4 | 25 | inline BOOST_MP_CXX14_CONSTEXPR void add_unsigned(CppInt1& result, const CppInt2& a, const limb_type& o) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value) |
7c673cae FG |
26 | { |
27 | // Addition using modular arithmetic. | |
28 | // Nothing fancy, just let uintmax_t take the strain: | |
92f5a8d4 | 29 | if (&result != &a) |
7c673cae | 30 | result.resize(a.size(), a.size()); |
92f5a8d4 TL |
31 | double_limb_type carry = o; |
32 | typename CppInt1::limb_pointer pr = result.limbs(); | |
33 | typename CppInt2::const_limb_pointer pa = a.limbs(); | |
34 | unsigned i = 0; | |
7c673cae | 35 | // Addition with carry until we either run out of digits or carry is zero: |
92f5a8d4 | 36 | for (; carry && (i < result.size()); ++i) |
7c673cae FG |
37 | { |
38 | carry += static_cast<double_limb_type>(pa[i]); | |
39 | #ifdef __MSVC_RUNTIME_CHECKS | |
40 | pr[i] = static_cast<limb_type>(carry & ~static_cast<limb_type>(0)); | |
41 | #else | |
42 | pr[i] = static_cast<limb_type>(carry); | |
43 | #endif | |
44 | carry >>= CppInt1::limb_bits; | |
45 | } | |
46 | // Just copy any remaining digits: | |
92f5a8d4 | 47 | if (&a != &result) |
7c673cae | 48 | { |
20effc67 | 49 | std_constexpr::copy(pa + i, pa + a.size(), pr + i); |
7c673cae | 50 | } |
92f5a8d4 | 51 | if (carry) |
7c673cae FG |
52 | { |
53 | // We overflowed, need to add one more limb: | |
54 | unsigned x = result.size(); | |
55 | result.resize(x + 1, x + 1); | |
92f5a8d4 | 56 | if (result.size() > x) |
7c673cae FG |
57 | result.limbs()[x] = static_cast<limb_type>(carry); |
58 | } | |
59 | result.normalize(); | |
60 | result.sign(a.sign()); | |
61 | } | |
62 | // | |
7c673cae FG |
63 | // And again to subtract a single limb: |
64 | // | |
65 | template <class CppInt1, class CppInt2> | |
92f5a8d4 | 66 | inline BOOST_MP_CXX14_CONSTEXPR void subtract_unsigned(CppInt1& result, const CppInt2& a, const limb_type& b) BOOST_MP_NOEXCEPT_IF(is_non_throwing_cpp_int<CppInt1>::value) |
7c673cae FG |
67 | { |
68 | // Subtract one limb. | |
69 | // Nothing fancy, just let uintmax_t take the strain: | |
92f5a8d4 | 70 | #ifdef BOOST_NO_CXX14_CONSTEXPR |
7c673cae | 71 | BOOST_STATIC_CONSTANT(double_limb_type, borrow = static_cast<double_limb_type>(CppInt1::max_limb_value) + 1); |
92f5a8d4 TL |
72 | #else |
73 | constexpr double_limb_type borrow = static_cast<double_limb_type>(CppInt1::max_limb_value) + 1; | |
74 | #endif | |
7c673cae | 75 | result.resize(a.size(), a.size()); |
92f5a8d4 | 76 | typename CppInt1::limb_pointer pr = result.limbs(); |
7c673cae | 77 | typename CppInt2::const_limb_pointer pa = a.limbs(); |
92f5a8d4 | 78 | if (*pa >= b) |
7c673cae FG |
79 | { |
80 | *pr = *pa - b; | |
92f5a8d4 | 81 | if (&result != &a) |
7c673cae | 82 | { |
92f5a8d4 | 83 | std_constexpr::copy(pa + 1, pa + a.size(), pr + 1); |
7c673cae FG |
84 | result.sign(a.sign()); |
85 | } | |
92f5a8d4 | 86 | else if ((result.size() == 1) && (*pr == 0)) |
7c673cae FG |
87 | { |
88 | result.sign(false); // zero is unsigned. | |
89 | } | |
90 | } | |
92f5a8d4 | 91 | else if (result.size() == 1) |
7c673cae FG |
92 | { |
93 | *pr = b - *pa; | |
94 | result.sign(!a.sign()); | |
95 | } | |
96 | else | |
97 | { | |
92f5a8d4 | 98 | *pr = static_cast<limb_type>((borrow + *pa) - b); |
7c673cae | 99 | unsigned i = 1; |
92f5a8d4 | 100 | while (!pa[i]) |
7c673cae FG |
101 | { |
102 | pr[i] = CppInt1::max_limb_value; | |
103 | ++i; | |
104 | } | |
105 | pr[i] = pa[i] - 1; | |
92f5a8d4 | 106 | if (&result != &a) |
7c673cae FG |
107 | { |
108 | ++i; | |
92f5a8d4 | 109 | std_constexpr::copy(pa + i, pa + a.size(), pr + i); |
7c673cae FG |
110 | } |
111 | result.normalize(); | |
112 | result.sign(a.sign()); | |
113 | } | |
114 | } | |
115 | ||
116 | // | |
117 | // Now the actual functions called by the front end, all of which forward to one of the above: | |
118 | // | |
119 | 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> | |
92f5a8d4 TL |
120 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type |
121 | eval_add( | |
122 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
123 | const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae FG |
124 | { |
125 | eval_add(result, result, o); | |
126 | } | |
127 | 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, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3> | |
92f5a8d4 TL |
128 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type |
129 | eval_add( | |
130 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
131 | const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a, | |
132 | const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 133 | { |
92f5a8d4 | 134 | if (a.sign() != b.sign()) |
7c673cae FG |
135 | { |
136 | subtract_unsigned(result, a, b); | |
137 | return; | |
138 | } | |
139 | add_unsigned(result, a, b); | |
140 | } | |
141 | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | |
92f5a8d4 TL |
142 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type |
143 | eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 144 | { |
92f5a8d4 | 145 | if (result.sign()) |
7c673cae FG |
146 | { |
147 | subtract_unsigned(result, result, o); | |
148 | } | |
149 | else | |
150 | add_unsigned(result, result, o); | |
151 | } | |
152 | 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> | |
92f5a8d4 TL |
153 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type |
154 | eval_add( | |
155 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
156 | const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a, | |
157 | const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 158 | { |
92f5a8d4 | 159 | if (a.sign()) |
7c673cae FG |
160 | { |
161 | subtract_unsigned(result, a, o); | |
162 | } | |
163 | else | |
164 | add_unsigned(result, a, o); | |
165 | } | |
166 | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | |
92f5a8d4 TL |
167 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type |
168 | eval_add( | |
169 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
170 | const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 171 | { |
92f5a8d4 | 172 | if (o < 0) |
7c673cae | 173 | eval_subtract(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o))); |
92f5a8d4 | 174 | else if (o > 0) |
7c673cae FG |
175 | eval_add(result, static_cast<limb_type>(o)); |
176 | } | |
177 | 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> | |
92f5a8d4 TL |
178 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type |
179 | eval_add( | |
180 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
181 | const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a, | |
182 | const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 183 | { |
92f5a8d4 | 184 | if (o < 0) |
7c673cae | 185 | eval_subtract(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o))); |
92f5a8d4 | 186 | else if (o > 0) |
7c673cae | 187 | eval_add(result, a, static_cast<limb_type>(o)); |
92f5a8d4 | 188 | else if (&result != &a) |
7c673cae FG |
189 | result = a; |
190 | } | |
191 | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | |
92f5a8d4 TL |
192 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type |
193 | eval_subtract( | |
194 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
195 | const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 196 | { |
92f5a8d4 | 197 | if (result.sign()) |
7c673cae FG |
198 | { |
199 | add_unsigned(result, result, o); | |
200 | } | |
201 | else | |
202 | subtract_unsigned(result, result, o); | |
203 | } | |
204 | 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> | |
92f5a8d4 TL |
205 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type |
206 | eval_subtract( | |
207 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
208 | const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a, | |
209 | const limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 210 | { |
92f5a8d4 | 211 | if (a.sign()) |
7c673cae FG |
212 | { |
213 | add_unsigned(result, a, o); | |
214 | } | |
215 | else | |
216 | { | |
217 | subtract_unsigned(result, a, o); | |
218 | } | |
219 | } | |
220 | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | |
92f5a8d4 TL |
221 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type |
222 | eval_subtract( | |
223 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
224 | const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 225 | { |
92f5a8d4 | 226 | if (o) |
7c673cae | 227 | { |
92f5a8d4 | 228 | if (o < 0) |
7c673cae FG |
229 | eval_add(result, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o))); |
230 | else | |
231 | eval_subtract(result, static_cast<limb_type>(o)); | |
232 | } | |
233 | } | |
234 | 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> | |
92f5a8d4 TL |
235 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type |
236 | eval_subtract( | |
237 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
238 | const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a, | |
239 | const signed_limb_type& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 240 | { |
92f5a8d4 | 241 | if (o) |
7c673cae | 242 | { |
92f5a8d4 | 243 | if (o < 0) |
7c673cae FG |
244 | eval_add(result, a, static_cast<limb_type>(boost::multiprecision::detail::unsigned_abs(o))); |
245 | else | |
246 | eval_subtract(result, a, static_cast<limb_type>(o)); | |
247 | } | |
92f5a8d4 | 248 | else if (&result != &a) |
7c673cae FG |
249 | result = a; |
250 | } | |
251 | ||
252 | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | |
92f5a8d4 TL |
253 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type |
254 | eval_increment(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 255 | { |
92f5a8d4 | 256 | #ifdef BOOST_NO_CXX14_CONSTEXPR |
7c673cae | 257 | static const limb_type one = 1; |
92f5a8d4 TL |
258 | #else |
259 | constexpr const limb_type one = 1; | |
260 | #endif | |
261 | if (!result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value)) | |
7c673cae | 262 | ++result.limbs()[0]; |
11fdf7f2 TL |
263 | else if (result.sign() && result.limbs()[0]) |
264 | { | |
7c673cae | 265 | --result.limbs()[0]; |
11fdf7f2 TL |
266 | if (!result.limbs()[0]) |
267 | result.sign(false); | |
268 | } | |
7c673cae FG |
269 | else |
270 | eval_add(result, one); | |
271 | } | |
272 | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | |
92f5a8d4 TL |
273 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type |
274 | eval_decrement(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 275 | { |
92f5a8d4 | 276 | #ifdef BOOST_NO_CXX14_CONSTEXPR |
7c673cae | 277 | static const limb_type one = 1; |
92f5a8d4 TL |
278 | #else |
279 | constexpr const limb_type one = 1; | |
280 | #endif | |
281 | if (!result.sign() && result.limbs()[0]) | |
7c673cae | 282 | --result.limbs()[0]; |
11fdf7f2 | 283 | else if (result.sign() && (result.limbs()[0] < cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::max_limb_value)) |
7c673cae FG |
284 | ++result.limbs()[0]; |
285 | else | |
286 | eval_subtract(result, one); | |
287 | } | |
288 | 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> | |
92f5a8d4 TL |
289 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value>::type |
290 | eval_subtract( | |
291 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
292 | const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae FG |
293 | { |
294 | eval_subtract(result, result, o); | |
295 | } | |
296 | 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, unsigned MinBits3, unsigned MaxBits3, cpp_integer_type SignType3, cpp_int_check_type Checked3, class Allocator3> | |
92f5a8d4 TL |
297 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3> >::value>::type |
298 | eval_subtract( | |
299 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
300 | const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& a, | |
301 | const cpp_int_backend<MinBits3, MaxBits3, SignType3, Checked3, Allocator3>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 302 | { |
92f5a8d4 | 303 | if (a.sign() != b.sign()) |
7c673cae FG |
304 | { |
305 | add_unsigned(result, a, b); | |
306 | return; | |
307 | } | |
308 | subtract_unsigned(result, a, b); | |
309 | } | |
310 | ||
311 | // | |
312 | // Simple addition and subtraction routine for trivial cpp_int's come last: | |
313 | // | |
314 | // One of the arguments is signed: | |
315 | // | |
316 | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | |
92f5a8d4 TL |
317 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< |
318 | is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)>::type | |
319 | eval_add( | |
320 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
321 | const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 322 | { |
92f5a8d4 | 323 | if (result.sign() != o.sign()) |
7c673cae | 324 | { |
92f5a8d4 | 325 | if (*o.limbs() > *result.limbs()) |
7c673cae FG |
326 | { |
327 | *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | |
328 | result.negate(); | |
329 | } | |
330 | else | |
331 | *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | |
332 | } | |
333 | else | |
334 | *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | |
335 | result.normalize(); | |
336 | } | |
337 | // Simple version for two unsigned arguments: | |
338 | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | |
92f5a8d4 TL |
339 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< |
340 | is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | |
341 | eval_add(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
342 | const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae FG |
343 | { |
344 | *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | |
345 | result.normalize(); | |
346 | } | |
347 | ||
348 | // signed subtraction: | |
349 | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | |
92f5a8d4 TL |
350 | inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< |
351 | is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)>::type | |
352 | eval_subtract( | |
353 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
354 | const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae | 355 | { |
92f5a8d4 | 356 | if (result.sign() != o.sign()) |
7c673cae FG |
357 | { |
358 | *result.limbs() = detail::checked_add(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | |
359 | } | |
92f5a8d4 | 360 | else if (*result.limbs() < *o.limbs()) |
7c673cae FG |
361 | { |
362 | *result.limbs() = detail::checked_subtract(*o.limbs(), *result.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | |
363 | result.negate(); | |
364 | } | |
365 | else | |
366 | *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | |
367 | result.normalize(); | |
368 | } | |
369 | ||
370 | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | |
92f5a8d4 TL |
371 | BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< |
372 | is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | |
373 | eval_subtract( | |
374 | cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | |
375 | const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | |
7c673cae FG |
376 | { |
377 | *result.limbs() = detail::checked_subtract(*result.limbs(), *o.limbs(), typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | |
378 | result.normalize(); | |
379 | } | |
380 | ||
381 | #ifdef _MSC_VER | |
382 | #pragma warning(pop) | |
383 | #endif | |
384 | ||
92f5a8d4 | 385 | }}} // namespace boost::multiprecision::backends |
7c673cae FG |
386 | |
387 | #endif |