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