]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/multiprecision/performance/arithmetic_backend.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / multiprecision / performance / arithmetic_backend.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 #ifndef BOOST_MATH_FLOAT_BACKEND_HPP
7 #define BOOST_MATH_FLOAT_BACKEND_HPP
8
9 #include <iostream>
10 #include <iomanip>
11 #include <sstream>
12 #include <boost/cstdint.hpp>
13 #include <boost/lexical_cast.hpp>
14 #include <boost/math/concepts/real_concept.hpp>
15 #include <boost/multiprecision/number.hpp>
16 #include <boost/integer/common_factor_rt.hpp>
17 #include <boost/type_traits/common_type.hpp>
18 #include <boost/container_hash/hash.hpp>
19
20 namespace boost {
21 namespace multiprecision {
22 namespace backends {
23
24 #ifdef BOOST_MSVC
25 #pragma warning(push)
26 #pragma warning(disable : 4389 4244 4018 4244 4127)
27 #endif
28
29 template <class Arithmetic>
30 struct arithmetic_backend
31 {
32 typedef mpl::list<short, int, long, long long> signed_types;
33 typedef mpl::list<unsigned short, unsigned, unsigned long, unsigned long long> unsigned_types;
34 typedef mpl::list<float, double, long double> float_types;
35 typedef int exponent_type;
36
37 BOOST_MP_CXX14_CONSTEXPR arithmetic_backend() : m_value(0) {}
38 BOOST_MP_CXX14_CONSTEXPR arithmetic_backend(const arithmetic_backend& o) : m_value(o.m_value) {}
39 template <class A>
40 BOOST_MP_CXX14_CONSTEXPR arithmetic_backend(const A& o, const typename enable_if<is_arithmetic<A> >::type* = 0) : m_value(o) {}
41 template <class A>
42 BOOST_MP_CXX14_CONSTEXPR arithmetic_backend(const arithmetic_backend<A>& o) : m_value(o.data()) {}
43 BOOST_MP_CXX14_CONSTEXPR arithmetic_backend& operator=(const arithmetic_backend& o)
44 {
45 m_value = o.m_value;
46 return *this;
47 }
48 template <class A>
49 BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, arithmetic_backend&>::type operator=(A i)
50 {
51 m_value = i;
52 return *this;
53 }
54 template <class A>
55 BOOST_MP_CXX14_CONSTEXPR arithmetic_backend& operator=(const arithmetic_backend<A>& i)
56 {
57 m_value = i.data();
58 return *this;
59 }
60 arithmetic_backend& operator=(const char* s)
61 {
62 #ifndef BOOST_NO_EXCEPTIONS
63 try
64 {
65 #endif
66 m_value = boost::lexical_cast<Arithmetic>(s);
67 #ifndef BOOST_NO_EXCEPTIONS
68 }
69 catch (const bad_lexical_cast&)
70 {
71 throw std::runtime_error(std::string("Unable to interpret the string provided: \"") + s + std::string("\" as a compatible number type."));
72 }
73 #endif
74 return *this;
75 }
76 BOOST_MP_CXX14_CONSTEXPR void swap(arithmetic_backend& o)
77 {
78 std::swap(m_value, o.m_value);
79 }
80 std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
81 {
82 std::stringstream ss;
83 ss.flags(f);
84 ss << std::setprecision(digits ? digits : std::numeric_limits<Arithmetic>::digits10 + 4) << m_value;
85 return ss.str();
86 }
87 BOOST_MP_CXX14_CONSTEXPR void do_negate(const mpl::true_&)
88 {
89 m_value = 1 + ~m_value;
90 }
91 BOOST_MP_CXX14_CONSTEXPR void do_negate(const mpl::false_&)
92 {
93 m_value = -m_value;
94 }
95 BOOST_MP_CXX14_CONSTEXPR void negate()
96 {
97 do_negate(mpl::bool_<is_unsigned<Arithmetic>::value>());
98 }
99 BOOST_MP_CXX14_CONSTEXPR int compare(const arithmetic_backend& o) const
100 {
101 return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0);
102 }
103 template <class A>
104 BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, int>::type compare(A i) const
105 {
106 return m_value > static_cast<Arithmetic>(i) ? 1 : (m_value < static_cast<Arithmetic>(i) ? -1 : 0);
107 }
108 BOOST_MP_CXX14_CONSTEXPR Arithmetic& data() { return m_value; }
109 BOOST_MP_CXX14_CONSTEXPR const Arithmetic& data() const { return m_value; }
110
111 private:
112 Arithmetic m_value;
113 };
114
115 template <class R, class Arithmetic>
116 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const arithmetic_backend<Arithmetic>& backend)
117 {
118 typedef typename boost::common_type<R, Arithmetic>::type c_type;
119 BOOST_CONSTEXPR const c_type max = static_cast<c_type>((std::numeric_limits<R>::max)());
120 BOOST_CONSTEXPR const c_type min = static_cast<c_type>((std::numeric_limits<R>::min)());
121 c_type ct = static_cast<c_type>(backend.data());
122 if ((backend.data() < 0) && !std::numeric_limits<R>::is_signed)
123 BOOST_THROW_EXCEPTION(std::range_error("Attempt to convert negative number to unsigned type."));
124 if (ct > max)
125 *result = boost::is_signed<R>::value ? (std::numeric_limits<R>::max)() : backend.data();
126 else if (std::numeric_limits<Arithmetic>::is_signed && (ct < min))
127 *result = (std::numeric_limits<R>::min)();
128 else
129 *result = backend.data();
130 }
131
132 template <class R, class Arithmetic>
133 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const arithmetic_backend<Arithmetic>& backend)
134 {
135 *result = backend.data();
136 }
137
138 template <class Arithmetic>
139 inline BOOST_MP_CXX14_CONSTEXPR bool eval_eq(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
140 {
141 return a.data() == b.data();
142 }
143 template <class Arithmetic, class A2>
144 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2>, bool>::type eval_eq(const arithmetic_backend<Arithmetic>& a, const A2& b)
145 {
146 return a.data() == static_cast<Arithmetic>(b);
147 }
148 template <class Arithmetic>
149 inline BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
150 {
151 return a.data() < b.data();
152 }
153 template <class Arithmetic, class A2>
154 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2>, bool>::type eval_lt(const arithmetic_backend<Arithmetic>& a, const A2& b)
155 {
156 return a.data() < static_cast<Arithmetic>(b);
157 }
158 template <class Arithmetic>
159 inline BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
160 {
161 return a.data() > b.data();
162 }
163 template <class Arithmetic, class A2>
164 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2>, bool>::type eval_gt(const arithmetic_backend<Arithmetic>& a, const A2& b)
165 {
166 return a.data() > static_cast<Arithmetic>(b);
167 }
168
169 template <class Arithmetic>
170 inline BOOST_MP_CXX14_CONSTEXPR void eval_add(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
171 {
172 result.data() += o.data();
173 }
174 template <class Arithmetic>
175 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
176 {
177 result.data() -= o.data();
178 }
179 template <class Arithmetic>
180 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
181 {
182 result.data() *= o.data();
183 }
184 template <class Arithmetic>
185 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
186 {
187 result.data() /= o.data();
188 }
189 template <class Arithmetic>
190 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
191 {
192 if (!o.data())
193 BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero"));
194 result.data() /= o.data();
195 }
196
197 template <class Arithmetic, class A2>
198 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_add(arithmetic_backend<Arithmetic>& result, const A2& o)
199 {
200 result.data() += o;
201 }
202 template <class Arithmetic, class A2>
203 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_subtract(arithmetic_backend<Arithmetic>& result, const A2& o)
204 {
205 result.data() -= o;
206 }
207 template <class Arithmetic, class A2>
208 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_multiply(arithmetic_backend<Arithmetic>& result, const A2& o)
209 {
210 result.data() *= o;
211 }
212 template <class Arithmetic, class A2>
213 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && !std::numeric_limits<Arithmetic>::has_infinity)>::type
214 eval_divide(arithmetic_backend<Arithmetic>& result, const A2& o)
215 {
216 if (!o)
217 BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero"));
218 result.data() /= o;
219 }
220 template <class Arithmetic, class A2>
221 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && std::numeric_limits<Arithmetic>::has_infinity)>::type
222 eval_divide(arithmetic_backend<Arithmetic>& result, const A2& o)
223 {
224 result.data() /= o;
225 }
226
227 template <class Arithmetic>
228 inline BOOST_MP_CXX14_CONSTEXPR void eval_add(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
229 {
230 result.data() = a.data() + b.data();
231 }
232 template <class Arithmetic>
233 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
234 {
235 result.data() = a.data() - b.data();
236 }
237 template <class Arithmetic>
238 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
239 {
240 result.data() = a.data() * b.data();
241 }
242 template <class Arithmetic>
243 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
244 {
245 result.data() = a.data() / b.data();
246 }
247 template <class Arithmetic>
248 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<std::numeric_limits<Arithmetic>::has_infinity>::type eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
249 {
250 if (!b.data())
251 BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero"));
252 result.data() = a.data() / b.data();
253 }
254
255 template <class Arithmetic, class A2>
256 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_add(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b)
257 {
258 result.data() = a.data() + b;
259 }
260 template <class Arithmetic, class A2>
261 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_subtract(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b)
262 {
263 result.data() = a.data() - b;
264 }
265 template <class Arithmetic, class A2>
266 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A2> >::type eval_multiply(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b)
267 {
268 result.data() = a.data() * b;
269 }
270 template <class Arithmetic, class A2>
271 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && !std::numeric_limits<Arithmetic>::has_infinity)>::type
272 eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b)
273 {
274 if (!b)
275 BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero"));
276 result.data() = a.data() / b;
277 }
278 template <class Arithmetic, class A2>
279 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_arithmetic<A2>::value && std::numeric_limits<Arithmetic>::has_infinity)>::type
280 eval_divide(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const A2& b)
281 {
282 result.data() = a.data() / b;
283 }
284
285 template <class Arithmetic>
286 inline BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const arithmetic_backend<Arithmetic>& val)
287 {
288 return val.data() == 0;
289 }
290
291 template <class Arithmetic>
292 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
293 (!std::numeric_limits<Arithmetic>::is_specialized || std::numeric_limits<Arithmetic>::is_signed), int>::type
294 eval_get_sign(const arithmetic_backend<Arithmetic>& val)
295 {
296 return val.data() == 0 ? 0 : val.data() < 0 ? -1 : 1;
297 }
298 template <class Arithmetic>
299 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<
300 (std::numeric_limits<Arithmetic>::is_specialized || std::numeric_limits<Arithmetic>::is_signed), int>::type
301 eval_get_sign(const arithmetic_backend<Arithmetic>& val)
302 {
303 return val.data() == 0 ? 0 : 1;
304 }
305
306 template <class T>
307 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_unsigned<T>, T>::type abs(T v) { return v; }
308
309 template <class Arithmetic>
310 inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
311 {
312 using boost::multiprecision::backends::abs;
313 using std::abs;
314 result.data() = abs(o.data());
315 }
316
317 template <class Arithmetic>
318 inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
319 {
320 result.data() = std::abs(o.data());
321 }
322
323 template <class Arithmetic>
324 inline BOOST_MP_CXX14_CONSTEXPR void eval_floor(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
325 {
326 BOOST_MATH_STD_USING
327 result.data() = floor(o.data());
328 }
329
330 template <class Arithmetic>
331 inline BOOST_MP_CXX14_CONSTEXPR void eval_ceil(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
332 {
333 BOOST_MATH_STD_USING
334 result.data() = ceil(o.data());
335 }
336
337 template <class Arithmetic>
338 inline BOOST_MP_CXX14_CONSTEXPR void eval_sqrt(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
339 {
340 BOOST_MATH_STD_USING
341 result.data() = sqrt(o.data());
342 }
343
344 template <class Arithmetic>
345 inline BOOST_MP_CXX14_CONSTEXPR int eval_fpclassify(const arithmetic_backend<Arithmetic>& o)
346 {
347 return (boost::math::fpclassify)(o.data());
348 }
349
350 template <class Arithmetic>
351 inline BOOST_MP_CXX14_CONSTEXPR void eval_trunc(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
352 {
353 BOOST_MATH_STD_USING
354 result.data() = trunc(o.data());
355 }
356
357 template <class Arithmetic>
358 inline BOOST_MP_CXX14_CONSTEXPR void eval_round(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
359 {
360 BOOST_MATH_STD_USING
361 result.data() = round(o.data());
362 }
363
364 template <class Arithmetic>
365 inline BOOST_MP_CXX14_CONSTEXPR void eval_frexp(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, int* v)
366 {
367 BOOST_MATH_STD_USING
368 result.data() = frexp(a.data(), v);
369 }
370
371 template <class Arithmetic>
372 inline BOOST_MP_CXX14_CONSTEXPR void eval_ldexp(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, int v)
373 {
374 BOOST_MATH_STD_USING
375 result.data() = ldexp(a.data(), v);
376 }
377
378 template <class Arithmetic>
379 inline BOOST_MP_CXX14_CONSTEXPR void eval_exp(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
380 {
381 BOOST_MATH_STD_USING
382 result.data() = exp(o.data());
383 }
384
385 template <class Arithmetic>
386 inline BOOST_MP_CXX14_CONSTEXPR void eval_log(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
387 {
388 BOOST_MATH_STD_USING
389 result.data() = log(o.data());
390 }
391
392 template <class Arithmetic>
393 inline BOOST_MP_CXX14_CONSTEXPR void eval_log10(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
394 {
395 BOOST_MATH_STD_USING
396 result.data() = log10(o.data());
397 }
398
399 template <class Arithmetic>
400 inline BOOST_MP_CXX14_CONSTEXPR void eval_sin(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
401 {
402 BOOST_MATH_STD_USING
403 result.data() = sin(o.data());
404 }
405
406 template <class Arithmetic>
407 inline BOOST_MP_CXX14_CONSTEXPR void eval_cos(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
408 {
409 BOOST_MATH_STD_USING
410 result.data() = cos(o.data());
411 }
412
413 template <class Arithmetic>
414 inline BOOST_MP_CXX14_CONSTEXPR void eval_tan(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
415 {
416 BOOST_MATH_STD_USING
417 result.data() = tan(o.data());
418 }
419
420 template <class Arithmetic>
421 inline BOOST_MP_CXX14_CONSTEXPR void eval_acos(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
422 {
423 BOOST_MATH_STD_USING
424 result.data() = acos(o.data());
425 }
426
427 template <class Arithmetic>
428 inline BOOST_MP_CXX14_CONSTEXPR void eval_asin(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
429 {
430 BOOST_MATH_STD_USING
431 result.data() = asin(o.data());
432 }
433
434 template <class Arithmetic>
435 inline BOOST_MP_CXX14_CONSTEXPR void eval_atan(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
436 {
437 BOOST_MATH_STD_USING
438 result.data() = atan(o.data());
439 }
440
441 template <class Arithmetic>
442 inline BOOST_MP_CXX14_CONSTEXPR void eval_sinh(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
443 {
444 BOOST_MATH_STD_USING
445 result.data() = sinh(o.data());
446 }
447
448 template <class Arithmetic>
449 inline BOOST_MP_CXX14_CONSTEXPR void eval_cosh(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
450 {
451 BOOST_MATH_STD_USING
452 result.data() = cosh(o.data());
453 }
454
455 template <class Arithmetic>
456 inline BOOST_MP_CXX14_CONSTEXPR void eval_tanh(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& o)
457 {
458 BOOST_MATH_STD_USING
459 result.data() = tanh(o.data());
460 }
461
462 template <class Arithmetic>
463 inline BOOST_MP_CXX14_CONSTEXPR void eval_fmod(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
464 {
465 BOOST_MATH_STD_USING
466 result.data() = fmod(a.data(), b.data());
467 }
468
469 template <class Arithmetic>
470 inline BOOST_MP_CXX14_CONSTEXPR void eval_pow(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
471 {
472 BOOST_MATH_STD_USING
473 result.data() = pow(a.data(), b.data());
474 }
475
476 template <class Arithmetic>
477 inline BOOST_MP_CXX14_CONSTEXPR void eval_atan2(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
478 {
479 BOOST_MATH_STD_USING
480 result.data() = atan2(a.data(), b.data());
481 }
482
483 template <class Arithmetic, class I>
484 inline BOOST_MP_CXX14_CONSTEXPR void eval_left_shift(arithmetic_backend<Arithmetic>& result, I val)
485 {
486 result.data() <<= val;
487 }
488
489 template <class Arithmetic, class I>
490 inline BOOST_MP_CXX14_CONSTEXPR void eval_right_shift(arithmetic_backend<Arithmetic>& result, I val)
491 {
492 result.data() >>= val;
493 }
494
495 template <class Arithmetic>
496 inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a)
497 {
498 result.data() %= a.data();
499 }
500
501 template <class Arithmetic>
502 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a)
503 {
504 result.data() &= a.data();
505 }
506
507 template <class Arithmetic>
508 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a)
509 {
510 result.data() |= a.data();
511 }
512
513 template <class Arithmetic>
514 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a)
515 {
516 result.data() ^= a.data();
517 }
518
519 template <class Arithmetic>
520 inline BOOST_MP_CXX14_CONSTEXPR void eval_complement(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a)
521 {
522 result.data() = ~a.data();
523 }
524
525 template <class Arithmetic>
526 inline BOOST_MP_CXX14_CONSTEXPR void eval_gcd(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
527 {
528 result.data() = boost::integer::gcd(a.data(), b.data());
529 }
530
531 template <class Arithmetic>
532 inline BOOST_MP_CXX14_CONSTEXPR void eval_lcm(arithmetic_backend<Arithmetic>& result, const arithmetic_backend<Arithmetic>& a, const arithmetic_backend<Arithmetic>& b)
533 {
534 result.data() = boost::integer::lcm(a.data(), b.data());
535 }
536
537 template <class Arithmetic>
538 inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const arithmetic_backend<Arithmetic>& a)
539 {
540 boost::hash<Arithmetic> hasher;
541 return hasher(a.data());
542 }
543
544 #ifdef BOOST_MSVC
545 #pragma warning(pop)
546 #endif
547
548 } // namespace backends
549
550 using boost::multiprecision::backends::arithmetic_backend;
551
552 template <class Arithmetic>
553 struct number_category<arithmetic_backend<Arithmetic> > : public mpl::int_<is_integral<Arithmetic>::value ? number_kind_integer : number_kind_floating_point>
554 {};
555
556 namespace detail {
557
558 template <class Backend>
559 struct double_precision_type;
560
561 template <class Arithmetic, boost::multiprecision::expression_template_option ET>
562 struct double_precision_type<number<arithmetic_backend<Arithmetic>, ET> >
563 {
564 typedef number<arithmetic_backend<typename double_precision_type<Arithmetic>::type>, ET> type;
565 };
566 template <>
567 struct double_precision_type<arithmetic_backend<boost::int32_t> >
568 {
569 typedef arithmetic_backend<boost::int64_t> type;
570 };
571
572 } // namespace detail
573
574 }} // namespace boost::multiprecision
575 #if !(defined(__SGI_STL_PORT) || defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS))
576 //
577 // We shouldn't need these to get code to compile, however for the sake of
578 // "level playing field" performance comparisons they avoid the very slow
579 // lexical_cast's that would otherwise take place. Definition has to be guarded
580 // by the inverse of pp-logic in real_concept.hpp which defines these as a workaround
581 // for STLPort plus some other old/broken standartd libraries.
582 //
583 namespace boost { namespace math { namespace tools {
584
585 template <>
586 inline unsigned int real_cast<unsigned int, concepts::real_concept>(concepts::real_concept r)
587 {
588 return static_cast<unsigned int>(r.value());
589 }
590
591 template <>
592 inline int real_cast<int, concepts::real_concept>(concepts::real_concept r)
593 {
594 return static_cast<int>(r.value());
595 }
596
597 template <>
598 inline long real_cast<long, concepts::real_concept>(concepts::real_concept r)
599 {
600 return static_cast<long>(r.value());
601 }
602
603 // Converts from T to narrower floating-point types, float, double & long double.
604
605 template <>
606 inline float real_cast<float, concepts::real_concept>(concepts::real_concept r)
607 {
608 return static_cast<float>(r.value());
609 }
610 template <>
611 inline double real_cast<double, concepts::real_concept>(concepts::real_concept r)
612 {
613 return static_cast<double>(r.value());
614 }
615 template <>
616 inline long double real_cast<long double, concepts::real_concept>(concepts::real_concept r)
617 {
618 return r.value();
619 }
620
621 }}} // namespace boost::math::tools
622 #endif
623
624 namespace std {
625
626 template <class Arithmetic, boost::multiprecision::expression_template_option ExpressionTemplates>
627 class numeric_limits<boost::multiprecision::number<boost::multiprecision::arithmetic_backend<Arithmetic>, ExpressionTemplates> > : public std::numeric_limits<Arithmetic>
628 {
629 typedef std::numeric_limits<Arithmetic> base_type;
630 typedef boost::multiprecision::number<boost::multiprecision::arithmetic_backend<Arithmetic>, ExpressionTemplates> number_type;
631
632 public:
633 BOOST_STATIC_CONSTEXPR number_type(min)() BOOST_NOEXCEPT { return (base_type::min)(); }
634 BOOST_STATIC_CONSTEXPR number_type(max)() BOOST_NOEXCEPT { return (base_type::max)(); }
635 BOOST_STATIC_CONSTEXPR number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
636 BOOST_STATIC_CONSTEXPR number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); }
637 BOOST_STATIC_CONSTEXPR number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; }
638 BOOST_STATIC_CONSTEXPR number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); }
639 BOOST_STATIC_CONSTEXPR number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); }
640 BOOST_STATIC_CONSTEXPR number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); }
641 BOOST_STATIC_CONSTEXPR number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); }
642 };
643
644 template <>
645 class numeric_limits<boost::math::concepts::real_concept> : public std::numeric_limits<long double>
646 {
647 typedef std::numeric_limits<long double> base_type;
648 typedef boost::math::concepts::real_concept number_type;
649
650 public:
651 static const number_type(min)() BOOST_NOEXCEPT { return (base_type::min)(); }
652 static const number_type(max)() BOOST_NOEXCEPT { return (base_type::max)(); }
653 static const number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
654 static const number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); }
655 static const number_type round_error() BOOST_NOEXCEPT { return epsilon() / 2; }
656 static const number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); }
657 static const number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); }
658 static const number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); }
659 static const number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); }
660 };
661
662 } // namespace std
663
664 #include <boost/multiprecision/detail/integer_ops.hpp>
665
666 #endif