1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright 2011 John Maddock. Distributed under the Boost
3 // Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #ifndef BOOST_MATH_BIG_NUM_DEF_OPS
7 #define BOOST_MATH_BIG_NUM_DEF_OPS
9 #include <boost/math/policies/error_handling.hpp>
10 #include <boost/multiprecision/detail/number_base.hpp>
11 #include <boost/math/special_functions/fpclassify.hpp>
12 #include <boost/math/special_functions/next.hpp>
13 #include <boost/math/special_functions/hypot.hpp>
14 #include <boost/utility/enable_if.hpp>
15 #include <boost/mpl/front.hpp>
16 #include <boost/mpl/fold.hpp>
17 #include <boost/cstdint.hpp>
18 #include <boost/type_traits/make_unsigned.hpp>
19 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
20 #include <string_view>
23 #ifndef INSTRUMENT_BACKEND
24 #ifndef BOOST_MP_INSTRUMENT
25 #define INSTRUMENT_BACKEND(x)
27 #define INSTRUMENT_BACKEND(x) \
28 std::cout << BOOST_STRINGIZE(x) << " = " << x.str(0, std::ios_base::scientific) << std::endl;
33 namespace multiprecision {
40 template <class To, class From>
41 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
42 template <class To, class From>
43 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
44 template <class To, class From>
45 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/);
46 template <class To, class From>
47 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/);
48 template <class To, class From>
49 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
53 namespace default_ops {
56 // warning C4127: conditional expression is constant
57 // warning C4146: unary minus operator applied to unsigned type, result still unsigned
59 #pragma warning(disable : 4127 4146)
62 // Default versions of mixed arithmetic, these just construct a temporary
63 // from the arithmetic value and then do the arithmetic on that, two versions
64 // of each depending on whether the backend can be directly constructed from type V.
66 // Note that we have to provide *all* the template parameters to class number when used in
67 // enable_if as MSVC-10 won't compile the code if we rely on a computed-default parameter.
68 // Since the result of the test doesn't depend on whether expression templates are on or off
69 // we just use et_on everywhere. We could use a BOOST_WORKAROUND but that just obfuscates the
72 template <class T, class V>
73 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<is_convertible<V, T>::value>::type
74 eval_add(T& result, V const& v)
80 template <class T, class V>
81 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, T>::value>::type
82 eval_add(T& result, V const& v)
87 template <class T, class V>
88 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<is_convertible<V, T>::value>::type
89 eval_subtract(T& result, V const& v)
93 eval_subtract(result, t);
95 template <class T, class V>
96 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, T>::value>::type
97 eval_subtract(T& result, V const& v)
100 eval_subtract(result, t);
102 template <class T, class V>
103 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<is_convertible<V, T>::value>::type
104 eval_multiply(T& result, V const& v)
108 eval_multiply(result, t);
110 template <class T, class V>
111 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, T>::value>::type
112 eval_multiply(T& result, V const& v)
115 eval_multiply(result, t);
118 template <class T, class U, class V>
119 BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v);
121 template <class T, class U, class V>
122 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
125 eval_multiply(z, u, v);
128 template <class T, class U, class V>
129 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
131 eval_multiply_add(t, v, u);
133 template <class T, class U, class V>
134 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
137 eval_multiply(z, u, v);
140 template <class T, class U, class V>
141 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
143 eval_multiply_subtract(t, v, u);
145 template <class T, class V>
146 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
147 eval_divide(T& result, V const& v)
151 eval_divide(result, t);
153 template <class T, class V>
154 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
155 eval_divide(T& result, V const& v)
158 eval_divide(result, t);
160 template <class T, class V>
161 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
162 eval_modulus(T& result, V const& v)
166 eval_modulus(result, t);
168 template <class T, class V>
169 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
170 eval_modulus(T& result, V const& v)
173 eval_modulus(result, t);
175 template <class T, class V>
176 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
177 eval_bitwise_and(T& result, V const& v)
181 eval_bitwise_and(result, t);
183 template <class T, class V>
184 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
185 eval_bitwise_and(T& result, V const& v)
188 eval_bitwise_and(result, t);
190 template <class T, class V>
191 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
192 eval_bitwise_or(T& result, V const& v)
196 eval_bitwise_or(result, t);
198 template <class T, class V>
199 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
200 eval_bitwise_or(T& result, V const& v)
203 eval_bitwise_or(result, t);
205 template <class T, class V>
206 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
207 eval_bitwise_xor(T& result, V const& v)
211 eval_bitwise_xor(result, t);
213 template <class T, class V>
214 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
215 eval_bitwise_xor(T& result, V const& v)
218 eval_bitwise_xor(result, t);
221 template <class T, class V>
222 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
223 eval_complement(T& result, V const& v)
227 eval_complement(result, t);
229 template <class T, class V>
230 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
231 eval_complement(T& result, V const& v)
234 eval_complement(result, t);
238 // Default versions of 3-arg arithmetic functions, these mostly just forward to the 2 arg versions:
240 template <class T, class U, class V>
241 BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v);
244 inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const T& u, const T& v)
260 template <class T, class U>
261 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
267 template <class T, class U>
268 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
273 template <class T, class U>
274 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_add_default(T& t, const U& u, const T& v)
278 template <class T, class U, class V>
279 inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const U& u, const V& v)
281 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
291 template <class T, class U, class V>
292 inline BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v)
294 eval_add_default(t, u, v);
297 template <class T, class U, class V>
298 void BOOST_MP_CXX14_CONSTEXPR eval_subtract(T& t, const U& u, const V& v);
301 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const T& u, const T& v)
303 if ((&t == &v) && is_signed_number<T>::value)
318 template <class T, class U>
319 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
323 eval_subtract(t, u, vv);
325 template <class T, class U>
326 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
329 eval_subtract(t, u, vv);
331 template <class T, class U>
332 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
334 eval_subtract(t, v, u);
337 template <class T, class U>
338 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
342 eval_subtract(t, temp, v);
344 template <class T, class U>
345 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
348 eval_subtract(t, temp, v);
350 template <class T, class U, class V>
351 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const U& u, const V& v)
353 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
364 template <class T, class U, class V>
365 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(T& t, const U& u, const V& v)
367 eval_subtract_default(t, u, v);
371 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const T& u, const T& v)
387 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
388 template <class T, class U>
389 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
393 eval_multiply(t, u, vv);
395 template <class T, class U>
396 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
399 eval_multiply(t, u, vv);
401 template <class T, class U>
402 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_multiply_default(T& t, const U& u, const T& v)
404 eval_multiply(t, v, u);
407 template <class T, class U, class V>
408 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const U& u, const V& v)
410 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
416 t = number<T>::canonical_value(u);
420 template <class T, class U, class V>
421 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v)
423 eval_multiply_default(t, u, v);
427 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_add(T& t, const T& u, const T& v, const T& x)
429 if ((void*)&x == (void*)&t)
432 z = number<T>::canonical_value(x);
433 eval_multiply_add(t, u, v, z);
437 eval_multiply(t, u, v);
442 template <class T, class U>
443 inline BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<boost::is_same<T, U>::value, T>::type make_T(const U& u)
446 t = number<T>::canonical_value(u);
450 inline BOOST_MP_CXX14_CONSTEXPR const T& make_T(const T& t)
455 template <class T, class U, class V, class X>
456 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
458 eval_multiply_add(t, make_T<T>(u), make_T<T>(v), make_T<T>(x));
460 template <class T, class U, class V, class X>
461 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
463 eval_multiply_add(t, v, u, x);
465 template <class T, class U, class V, class X>
466 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
468 if ((void*)&x == (void*)&t)
472 eval_multiply_subtract(t, u, v, z);
476 eval_multiply(t, u, v);
480 template <class T, class U, class V, class X>
481 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
483 eval_multiply_subtract(t, v, u, x);
486 template <class T, class U, class V>
487 BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v);
490 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const T& u, const T& v)
497 eval_divide(temp, u, v);
506 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
507 template <class T, class U>
508 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
512 eval_divide(t, u, vv);
514 template <class T, class U>
515 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
518 eval_divide(t, u, vv);
520 template <class T, class U>
521 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
525 eval_divide(t, uu, v);
527 template <class T, class U>
528 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
531 eval_divide(t, uu, v);
534 template <class T, class U, class V>
535 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const U& u, const V& v)
537 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
541 eval_divide(temp, v);
550 template <class T, class U, class V>
551 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v)
553 eval_divide_default(t, u, v);
556 template <class T, class U, class V>
557 BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v);
560 inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const T& u, const T& v)
567 eval_modulus(temp, u, v);
576 template <class T, class U>
577 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
581 eval_modulus(t, u, vv);
583 template <class T, class U>
584 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
587 eval_modulus(t, u, vv);
589 template <class T, class U>
590 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
594 eval_modulus(t, uu, v);
596 template <class T, class U>
597 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
600 eval_modulus(t, uu, v);
602 template <class T, class U, class V>
603 inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const U& u, const V& v)
605 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
608 eval_modulus(temp, v);
617 template <class T, class U, class V>
618 inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v)
620 eval_modulus_default(t, u, v);
623 template <class T, class U, class V>
624 BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v);
627 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and_default(T& t, const T& u, const T& v)
631 eval_bitwise_and(t, u);
635 eval_bitwise_and(t, v);
640 eval_bitwise_and(t, v);
643 template <class T, class U>
644 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
648 eval_bitwise_and(t, u, vv);
650 template <class T, class U>
651 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
654 eval_bitwise_and(t, u, vv);
656 template <class T, class U>
657 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v)
659 eval_bitwise_and(t, v, u);
661 template <class T, class U, class V>
662 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<is_same<T, U>::value || is_same<T, V>::value>::type eval_bitwise_and_default(T& t, const U& u, const V& v)
665 eval_bitwise_and(t, v);
667 template <class T, class U, class V>
668 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v)
670 eval_bitwise_and_default(t, u, v);
673 template <class T, class U, class V>
674 BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v);
677 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const T& u, const T& v)
681 eval_bitwise_or(t, u);
685 eval_bitwise_or(t, v);
690 eval_bitwise_or(t, v);
693 template <class T, class U>
694 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
698 eval_bitwise_or(t, u, vv);
700 template <class T, class U>
701 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
704 eval_bitwise_or(t, u, vv);
706 template <class T, class U>
707 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v)
709 eval_bitwise_or(t, v, u);
711 template <class T, class U, class V>
712 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const U& u, const V& v)
714 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
716 eval_bitwise_or(t, u);
721 eval_bitwise_or(t, v);
724 template <class T, class U, class V>
725 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v)
727 eval_bitwise_or_default(t, u, v);
730 template <class T, class U, class V>
731 BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v);
734 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const T& u, const T& v)
738 eval_bitwise_xor(t, u);
742 eval_bitwise_xor(t, v);
747 eval_bitwise_xor(t, v);
750 template <class T, class U>
751 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
755 eval_bitwise_xor(t, u, vv);
757 template <class T, class U>
758 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
761 eval_bitwise_xor(t, u, vv);
763 template <class T, class U>
764 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v)
766 eval_bitwise_xor(t, v, u);
768 template <class T, class U, class V>
769 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const U& u, const V& v)
771 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
773 eval_bitwise_xor(t, u);
778 eval_bitwise_xor(t, v);
781 template <class T, class U, class V>
782 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v)
784 eval_bitwise_xor_default(t, u, v);
788 inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(T& val)
790 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
791 eval_add(val, static_cast<ui_type>(1u));
794 inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(T& val)
796 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
797 eval_subtract(val, static_cast<ui_type>(1u));
800 template <class T, class V>
801 inline BOOST_MP_CXX14_CONSTEXPR void eval_left_shift(T& result, const T& arg, const V val)
804 eval_left_shift(result, val);
807 template <class T, class V>
808 inline BOOST_MP_CXX14_CONSTEXPR void eval_right_shift(T& result, const T& arg, const V val)
811 eval_right_shift(result, val);
815 inline BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const T& val)
817 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
818 return val.compare(static_cast<ui_type>(0)) == 0;
821 inline BOOST_MP_CXX14_CONSTEXPR int eval_get_sign(const T& val)
823 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
824 return val.compare(static_cast<ui_type>(0));
827 template <class T, class V, class U>
828 inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const mpl::int_<number_kind_rational>&)
833 eval_divide(result, t);
836 template <class T, class V, class U, int N>
837 inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const mpl::int_<N>&)
839 typedef typename component_type<number<T> >::type component_number_type;
841 component_number_type x(v1), y(v2);
842 assign_components(result, x.backend(), y.backend());
845 template <class T, class V, class U>
846 inline BOOST_MP_CXX14_CONSTEXPR void assign_components(T& result, const V& v1, const U& v2)
848 return assign_components_imp(result, v1, v2, typename number_category<T>::type());
850 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
851 template <class Result, class Traits>
852 inline void assign_from_string_view(Result& result, const std::basic_string_view<char, Traits>& view)
854 // since most (all?) backends require a const char* to construct from, we just
859 template <class Result, class Traits>
860 inline void assign_from_string_view(Result& result, const std::basic_string_view<char, Traits>& view_x, const std::basic_string_view<char, Traits>& view_y)
862 // since most (all?) backends require a const char* to construct from, we just
864 std::string x(view_x), y(view_y);
865 assign_components(result, x.c_str(), y.c_str());
868 template <class R, int b>
869 struct has_enough_bits
872 struct type : public mpl::and_<mpl::not_<is_same<R, T> >, mpl::bool_<std::numeric_limits<T>::digits >= b> >
879 BOOST_MP_CXX14_CONSTEXPR terminal(const R& v) : value(v) {}
880 BOOST_MP_CXX14_CONSTEXPR terminal() {}
881 BOOST_MP_CXX14_CONSTEXPR terminal& operator=(R val)
887 BOOST_MP_CXX14_CONSTEXPR operator R() const { return value; }
890 template <class R, class B>
891 struct calculate_next_larger_type
893 // Find which list we're looking through:
894 typedef typename mpl::if_<
896 typename B::signed_types,
899 typename B::unsigned_types,
900 typename B::float_types>::type>::type list_type;
901 // A predicate to find a type with enough bits:
902 typedef typename has_enough_bits<R, std::numeric_limits<R>::digits>::template type<mpl::_> pred_type;
903 // See if the last type is in the list, if so we have to start after this:
904 typedef typename mpl::find_if<
906 is_same<R, mpl::_> >::type start_last;
907 // Where we're starting from, either the start of the sequence or the last type found:
908 typedef typename mpl::if_<is_same<start_last, typename mpl::end<list_type>::type>, typename mpl::begin<list_type>::type, start_last>::type start_seq;
909 // The range we're searching:
910 typedef mpl::iterator_range<start_seq, typename mpl::end<list_type>::type> range;
911 // Find the next type:
912 typedef typename mpl::find_if<
914 pred_type>::type iter_type;
915 // Either the next type, or a "terminal" to indicate we've run out of types to search:
916 typedef typename mpl::eval_if<
917 is_same<typename mpl::end<list_type>::type, iter_type>,
918 mpl::identity<terminal<R> >,
919 mpl::deref<iter_type> >::type type;
922 template <class R, class T>
923 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_integral<R>::value, bool>::type check_in_range(const T& t)
925 // Can t fit in an R?
926 if ((t > 0) && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)()))
932 template <class R, class B>
933 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend)
935 typedef typename calculate_next_larger_type<R, B>::type next_type;
936 next_type n = next_type();
937 eval_convert_to(&n, backend);
938 if (!boost::is_unsigned<R>::value && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (n > (next_type)(std::numeric_limits<R>::max)()))
940 *result = (std::numeric_limits<R>::max)();
942 else if (std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (n < (next_type)(std::numeric_limits<R>::min)()))
944 *result = (std::numeric_limits<R>::min)();
947 *result = static_cast<R>(n);
950 template <class R, class B>
951 inline BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend)
953 typedef typename calculate_next_larger_type<R, B>::type next_type;
954 next_type n = next_type();
955 eval_convert_to(&n, backend);
956 if (std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && ((n > (next_type)(std::numeric_limits<R>::max)() || (n < (next_type) - (std::numeric_limits<R>::max)()))))
958 *result = n > 0 ? (std::numeric_limits<R>::max)() : -(std::numeric_limits<R>::max)();
961 *result = static_cast<R>(n);
964 template <class R, class B>
965 inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const mpl::false_&)
968 // We ran out of types to try for the conversion, try
969 // a lexical_cast and hope for the best:
971 if (std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed && (eval_get_sign(backend) < 0))
972 BOOST_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
975 result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0)));
977 catch (const bad_lexical_cast&)
979 if (eval_get_sign(backend) < 0)
981 *result = std::numeric_limits<R>::is_integer && std::numeric_limits<R>::is_signed ? (std::numeric_limits<R>::min)() : -(std::numeric_limits<R>::max)();
984 *result = (std::numeric_limits<R>::max)();
988 template <class R, class B>
989 inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const mpl::true_&)
992 // We ran out of types to try for the conversion, try
993 // a lexical_cast and hope for the best:
995 if (std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed && (eval_get_sign(backend) < 0))
996 BOOST_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
1000 R mask = ~static_cast<R>(0u);
1001 eval_bitwise_and(t, mask);
1002 result->value = boost::lexical_cast<R>(t.str(0, std::ios_base::fmtflags(0)));
1004 catch (const bad_lexical_cast&)
1006 if (eval_get_sign(backend) < 0)
1008 *result = std::numeric_limits<R>::is_integer && std::numeric_limits<R>::is_signed ? (std::numeric_limits<R>::min)() : -(std::numeric_limits<R>::max)();
1011 *result = (std::numeric_limits<R>::max)();
1015 template <class R, class B>
1016 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<R>* result, const B& backend)
1018 typedef mpl::bool_<boost::is_unsigned<R>::value && number_category<B>::value == number_kind_integer> tag_type;
1019 last_chance_eval_convert_to(result, backend, tag_type());
1022 template <class B1, class B2, expression_template_option et>
1023 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<number<B1, et> >* result, const B2& backend)
1026 // We ran out of types to try for the conversion, try
1027 // a generic conversion and hope for the best:
1029 boost::multiprecision::detail::generic_interconvert(result->value.backend(), backend, number_category<B1>(), number_category<B2>());
1033 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::string* result, const B& backend)
1035 *result = backend.str(0, std::ios_base::fmtflags(0));
1039 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<float>* result, const B& backend)
1041 typedef typename scalar_result_from_possible_complex<multiprecision::number<B> >::type scalar_type;
1043 eval_real(re.backend(), backend);
1044 eval_imag(im.backend(), backend);
1046 *result = std::complex<float>(re.template convert_to<float>(), im.template convert_to<float>());
1050 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<double>* result, const B& backend)
1052 typedef typename scalar_result_from_possible_complex<multiprecision::number<B> >::type scalar_type;
1054 eval_real(re.backend(), backend);
1055 eval_imag(im.backend(), backend);
1057 *result = std::complex<double>(re.template convert_to<double>(), im.template convert_to<double>());
1061 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<long double>* result, const B& backend)
1063 typedef typename scalar_result_from_possible_complex<multiprecision::number<B> >::type scalar_type;
1065 eval_real(re.backend(), backend);
1066 eval_imag(im.backend(), backend);
1068 *result = std::complex<long double>(re.template convert_to<long double>(), im.template convert_to<long double>());
1075 inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(T& result, const T& arg)
1077 typedef typename T::signed_types type_list;
1078 typedef typename mpl::front<type_list>::type front;
1080 if (arg.compare(front(0)) < 0)
1084 inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(T& result, const T& arg)
1086 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The fabs function is only valid for floating point types.");
1087 typedef typename T::signed_types type_list;
1088 typedef typename mpl::front<type_list>::type front;
1090 if (arg.compare(front(0)) < 0)
1094 template <class Backend>
1095 inline BOOST_MP_CXX14_CONSTEXPR int eval_fpclassify(const Backend& arg)
1097 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types.");
1098 return eval_is_zero(arg) ? FP_ZERO : FP_NORMAL;
1102 inline BOOST_MP_CXX14_CONSTEXPR void eval_fmod(T& result, const T& a, const T& b)
1104 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The fmod function is only valid for floating point types.");
1105 if ((&result == &a) || (&result == &b))
1108 eval_fmod(temp, a, b);
1112 switch (eval_fpclassify(a))
1119 result = std::numeric_limits<number<T> >::quiet_NaN().backend();
1123 switch (eval_fpclassify(b))
1127 result = std::numeric_limits<number<T> >::quiet_NaN().backend();
1132 eval_divide(result, a, b);
1133 if (eval_get_sign(result) < 0)
1134 eval_ceil(n, result);
1136 eval_floor(n, result);
1137 eval_multiply(n, b);
1138 eval_subtract(result, a, n);
1140 template <class T, class A>
1141 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const T& x, const A& a)
1143 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
1144 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
1147 eval_fmod(result, x, c);
1150 template <class T, class A>
1151 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const A& x, const T& a)
1153 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
1154 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
1157 eval_fmod(result, c, a);
1161 BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a);
1164 inline BOOST_MP_CXX14_CONSTEXPR void eval_remquo(T& result, const T& a, const T& b, int* pi)
1166 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The remquo function is only valid for floating point types.");
1167 if ((&result == &a) || (&result == &b))
1170 eval_remquo(temp, a, b, pi);
1175 eval_divide(result, a, b);
1176 eval_round(n, result);
1177 eval_convert_to(pi, n);
1178 eval_multiply(n, b);
1179 eval_subtract(result, a, n);
1181 template <class T, class A>
1182 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, void>::type eval_remquo(T& result, const T& x, const A& a, int* pi)
1184 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
1185 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
1186 cast_type c = cast_type();
1188 eval_remquo(result, x, c, pi);
1190 template <class T, class A>
1191 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, void>::type eval_remquo(T& result, const A& x, const T& a, int* pi)
1193 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
1194 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
1195 cast_type c = cast_type();
1197 eval_remquo(result, c, a, pi);
1199 template <class T, class U, class V>
1200 inline BOOST_MP_CXX14_CONSTEXPR void eval_remainder(T& result, const U& a, const V& b)
1203 eval_remquo(result, a, b, &i);
1207 BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const B& a, const B& b);
1208 template <class T, class U>
1209 BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const T& a, const U& b);
1211 BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const B& a, const B& b);
1212 template <class T, class U>
1213 BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const T& a, const U& b);
1216 inline BOOST_MP_CXX14_CONSTEXPR void eval_fdim(T& result, const T& a, const T& b)
1218 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1219 const ui_type zero = 0u;
1220 switch (eval_fpclassify(b))
1227 switch (eval_fpclassify(a))
1238 eval_subtract(result, a, b);
1244 template <class T, class A>
1245 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fdim(T& result, const T& a, const A& b)
1247 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1248 typedef typename boost::multiprecision::detail::canonical<A, T>::type arithmetic_type;
1249 const ui_type zero = 0u;
1250 arithmetic_type canonical_b = b;
1251 switch ((::boost::math::fpclassify)(b))
1258 switch (eval_fpclassify(a))
1267 if (eval_gt(a, canonical_b))
1269 eval_subtract(result, a, canonical_b);
1275 template <class T, class A>
1276 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fdim(T& result, const A& a, const T& b)
1278 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1279 typedef typename boost::multiprecision::detail::canonical<A, T>::type arithmetic_type;
1280 const ui_type zero = 0u;
1281 arithmetic_type canonical_a = a;
1282 switch (eval_fpclassify(b))
1289 switch ((::boost::math::fpclassify)(a))
1295 result = std::numeric_limits<number<T> >::infinity().backend();
1298 if (eval_gt(canonical_a, b))
1300 eval_subtract(result, canonical_a, b);
1307 inline BOOST_MP_CXX14_CONSTEXPR void eval_trunc(T& result, const T& a)
1309 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
1310 switch (eval_fpclassify(a))
1320 if (eval_get_sign(a) < 0)
1321 eval_ceil(result, a);
1323 eval_floor(result, a);
1327 inline BOOST_MP_CXX14_CONSTEXPR void eval_modf(T& result, T const& arg, T* pipart)
1329 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1330 int c = eval_fpclassify(arg);
1331 if (c == (int)FP_NAN)
1338 else if (c == (int)FP_INFINITE)
1342 result = ui_type(0u);
1347 eval_trunc(*pipart, arg);
1348 eval_subtract(result, arg, *pipart);
1353 eval_trunc(ipart, arg);
1354 eval_subtract(result, arg, ipart);
1359 inline BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a)
1361 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
1362 typedef typename boost::multiprecision::detail::canonical<float, T>::type fp_type;
1363 int c = eval_fpclassify(a);
1364 if (c == (int)FP_NAN)
1370 if ((c == FP_ZERO) || (c == (int)FP_INFINITE))
1374 else if (eval_get_sign(a) < 0)
1376 eval_subtract(result, a, fp_type(0.5f));
1377 eval_ceil(result, result);
1381 eval_add(result, a, fp_type(0.5f));
1382 eval_floor(result, result);
1387 BOOST_MP_CXX14_CONSTEXPR void eval_lcm(B& result, const B& a, const B& b);
1389 BOOST_MP_CXX14_CONSTEXPR void eval_gcd(B& result, const B& a, const B& b);
1391 template <class T, class Arithmetic>
1392 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const T& a, const Arithmetic& b)
1394 typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
1395 using default_ops::eval_gcd;
1397 t = static_cast<si_type>(b);
1398 eval_gcd(result, a, t);
1400 template <class T, class Arithmetic>
1401 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const Arithmetic& a, const T& b)
1403 eval_gcd(result, b, a);
1405 template <class T, class Arithmetic>
1406 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const T& a, const Arithmetic& b)
1408 typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
1409 using default_ops::eval_lcm;
1411 t = static_cast<si_type>(b);
1412 eval_lcm(result, a, t);
1414 template <class T, class Arithmetic>
1415 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const Arithmetic& a, const T& b)
1417 eval_lcm(result, b, a);
1421 inline BOOST_MP_CXX14_CONSTEXPR unsigned eval_lsb(const T& val)
1423 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1424 int c = eval_get_sign(val);
1427 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
1431 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
1433 unsigned result = 0;
1438 eval_bitwise_and(t, mask, val);
1440 eval_left_shift(mask, 1);
1441 } while (eval_is_zero(t));
1447 inline BOOST_MP_CXX14_CONSTEXPR int eval_msb(const T& val)
1449 int c = eval_get_sign(val);
1452 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
1456 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
1459 // This implementation is really really rubbish - it does
1460 // a linear scan for the most-significant-bit. We should really
1461 // do a binary search, but as none of our backends actually needs
1462 // this implementation, we'll leave it for now. In fact for most
1463 // backends it's likely that there will always be a more efficient
1464 // native implementation possible.
1466 unsigned result = 0;
1468 while (!eval_is_zero(t))
1470 eval_right_shift(t, 1);
1477 inline BOOST_MP_CXX14_CONSTEXPR bool eval_bit_test(const T& val, unsigned index)
1479 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1482 eval_left_shift(mask, index);
1483 eval_bitwise_and(t, mask, val);
1484 return !eval_is_zero(t);
1488 inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_set(T& val, unsigned index)
1490 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1493 eval_left_shift(mask, index);
1494 eval_bitwise_or(val, mask);
1498 inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_flip(T& val, unsigned index)
1500 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1503 eval_left_shift(mask, index);
1504 eval_bitwise_xor(val, mask);
1508 inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_unset(T& val, unsigned index)
1510 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1513 eval_left_shift(mask, index);
1514 eval_bitwise_and(t, mask, val);
1515 if (!eval_is_zero(t))
1516 eval_bitwise_xor(val, mask);
1520 void BOOST_MP_CXX14_CONSTEXPR eval_integer_sqrt(B& s, B& r, const B& x)
1523 // This is slow bit-by-bit integer square root, see for example
1524 // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
1525 // There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf
1526 // and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented
1529 typedef typename boost::multiprecision::detail::canonical<unsigned char, B>::type ui_type;
1532 if (eval_get_sign(x) == 0)
1537 int g = eval_msb(x);
1541 eval_subtract(r, x, s);
1550 eval_bit_set(t, 2 * g);
1551 eval_subtract(r, x, t);
1553 if (eval_get_sign(r) == 0)
1555 int msbr = eval_msb(r);
1558 if (msbr >= org_g + g + 1)
1561 eval_left_shift(t, g + 1);
1562 eval_bit_set(t, 2 * g);
1563 if (t.compare(r) <= 0)
1565 BOOST_ASSERT(g >= 0);
1567 eval_subtract(r, t);
1568 if (eval_get_sign(r) == 0)
1578 inline BOOST_MP_CXX14_CONSTEXPR void eval_conj(B& result, const B& val)
1580 result = val; // assume non-complex result.
1583 inline BOOST_MP_CXX14_CONSTEXPR void eval_proj(B& result, const B& val)
1585 result = val; // assume non-complex result.
1589 // These have to implemented by the backend, declared here so that our macro generated code compiles OK.
1592 typename enable_if_c<sizeof(T) == 0>::type eval_floor();
1594 typename enable_if_c<sizeof(T) == 0>::type eval_ceil();
1596 typename enable_if_c<sizeof(T) == 0>::type eval_trunc();
1598 typename enable_if_c<sizeof(T) == 0>::type eval_sqrt();
1600 typename enable_if_c<sizeof(T) == 0>::type eval_ldexp();
1602 typename enable_if_c<sizeof(T) == 0>::type eval_frexp();
1603 // TODO implement default versions of these:
1605 typename enable_if_c<sizeof(T) == 0>::type eval_asinh();
1607 typename enable_if_c<sizeof(T) == 0>::type eval_acosh();
1609 typename enable_if_c<sizeof(T) == 0>::type eval_atanh();
1612 // eval_logb and eval_scalbn simply assume base 2 and forward to
1613 // eval_ldexp and eval_frexp:
1616 inline BOOST_MP_CXX14_CONSTEXPR typename B::exponent_type eval_ilogb(const B& val)
1618 BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of ilogb requires a base 2 number type");
1619 typename B::exponent_type e(0);
1620 switch (eval_fpclassify(val))
1624 return FP_ILOGBNAN > 0 ? (std::numeric_limits<typename B::exponent_type>::max)() : (std::numeric_limits<typename B::exponent_type>::min)();
1626 return (std::numeric_limits<typename B::exponent_type>::max)();
1629 return (std::numeric_limits<typename B::exponent_type>::max)();
1631 return (std::numeric_limits<typename B::exponent_type>::min)();
1634 eval_frexp(result, val, &e);
1639 BOOST_MP_CXX14_CONSTEXPR int eval_signbit(const T& val);
1642 inline BOOST_MP_CXX14_CONSTEXPR void eval_logb(B& result, const B& val)
1644 switch (eval_fpclassify(val))
1651 result = std::numeric_limits<number<B> >::infinity().backend();
1657 if (eval_signbit(val))
1661 typedef typename boost::mpl::if_c<boost::is_same<boost::intmax_t, long>::value, boost::long_long_type, boost::intmax_t>::type max_t;
1662 result = static_cast<max_t>(eval_ilogb(val));
1664 template <class B, class A>
1665 inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbn(B& result, const B& val, A e)
1667 BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of scalbn requires a base 2 number type");
1668 eval_ldexp(result, val, static_cast<typename B::exponent_type>(e));
1670 template <class B, class A>
1671 inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbln(B& result, const B& val, A e)
1673 eval_scalbn(result, val, e);
1677 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, mpl::true_ const&, const mpl::false_&)
1679 return eval_fpclassify(val) == FP_NAN;
1682 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, mpl::false_ const&, const mpl::true_&)
1684 return (boost::math::isnan)(val);
1687 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T&, mpl::false_ const&, const mpl::false_&)
1693 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val)
1695 return is_arg_nan(val, mpl::bool_<boost::multiprecision::detail::is_backend<T>::value>(), is_floating_point<T>());
1698 template <class T, class U, class V>
1699 inline BOOST_MP_CXX14_CONSTEXPR void eval_fmax(T& result, const U& a, const V& b)
1702 result = number<T>::canonical_value(b);
1703 else if (is_arg_nan(b))
1704 result = number<T>::canonical_value(a);
1705 else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
1706 result = number<T>::canonical_value(b);
1708 result = number<T>::canonical_value(a);
1710 template <class T, class U, class V>
1711 inline BOOST_MP_CXX14_CONSTEXPR void eval_fmin(T& result, const U& a, const V& b)
1714 result = number<T>::canonical_value(b);
1715 else if (is_arg_nan(b))
1716 result = number<T>::canonical_value(a);
1717 else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
1718 result = number<T>::canonical_value(a);
1720 result = number<T>::canonical_value(b);
1723 template <class R, class T, class U>
1724 inline BOOST_MP_CXX14_CONSTEXPR void eval_hypot(R& result, const T& a, const U& b)
1727 // Normalize x and y, so that both are positive and x >= y:
1730 x = number<R>::canonical_value(a);
1731 y = number<R>::canonical_value(b);
1732 if (eval_get_sign(x) < 0)
1734 if (eval_get_sign(y) < 0)
1737 // Special case, see C99 Annex F.
1738 // The order of the if's is important: do not change!
1739 int c1 = eval_fpclassify(x);
1740 int c2 = eval_fpclassify(y);
1752 if (c1 == FP_INFINITE)
1757 if ((c2 == FP_INFINITE) || (c2 == FP_NAN))
1771 eval_multiply(result, x, std::numeric_limits<number<R> >::epsilon().backend());
1773 if (eval_gt(result, y))
1780 eval_divide(rat, y, x);
1781 eval_multiply(result, rat, rat);
1782 eval_increment(result);
1783 eval_sqrt(rat, result);
1784 eval_multiply(result, rat, x);
1787 template <class R, class T>
1788 inline BOOST_MP_CXX14_CONSTEXPR void eval_nearbyint(R& result, const T& a)
1790 eval_round(result, a);
1792 template <class R, class T>
1793 inline BOOST_MP_CXX14_CONSTEXPR void eval_rint(R& result, const T& a)
1795 eval_nearbyint(result, a);
1799 inline BOOST_MP_CXX14_CONSTEXPR int eval_signbit(const T& val)
1801 return eval_get_sign(val) < 0 ? 1 : 0;
1805 // Real and imaginary parts:
1807 template <class To, class From>
1808 inline BOOST_MP_CXX14_CONSTEXPR void eval_real(To& to, const From& from)
1812 template <class To, class From>
1813 inline BOOST_MP_CXX14_CONSTEXPR void eval_imag(To& to, const From&)
1815 typedef typename mpl::front<typename To::unsigned_types>::type ui_type;
1819 } // namespace default_ops
1820 namespace default_ops_adl {
1822 template <class To, class From>
1823 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real_imp(To& to, const From& from)
1825 typedef typename component_type<number<To> >::type to_component_type;
1826 typename to_component_type::backend_type to_component;
1827 to_component = from;
1828 eval_set_real(to, to_component);
1830 template <class To, class From>
1831 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag_imp(To& to, const From& from)
1833 typedef typename component_type<number<To> >::type to_component_type;
1834 typename to_component_type::backend_type to_component;
1835 to_component = from;
1836 eval_set_imag(to, to_component);
1839 } // namespace default_ops_adl
1840 namespace default_ops {
1842 template <class To, class From>
1843 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<To>::value == number_kind_complex>::type eval_set_real(To& to, const From& from)
1845 default_ops_adl::eval_set_real_imp(to, from);
1847 template <class To, class From>
1848 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<number_category<To>::value == number_kind_complex>::type eval_set_real(To& to, const From& from)
1853 template <class To, class From>
1854 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(To& to, const From& from)
1856 default_ops_adl::eval_set_imag_imp(to, from);
1860 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(T& to, const T& from)
1865 void BOOST_MP_CXX14_CONSTEXPR eval_set_imag(T&, const T&)
1867 BOOST_STATIC_ASSERT_MSG(sizeof(T) == INT_MAX, "eval_set_imag needs to be specialised for each specific backend");
1871 // These functions are implemented in separate files, but expanded inline here,
1872 // DO NOT CHANGE THE ORDER OF THESE INCLUDES:
1874 #include <boost/multiprecision/detail/functions/constants.hpp>
1875 #include <boost/multiprecision/detail/functions/pow.hpp>
1876 #include <boost/multiprecision/detail/functions/trig.hpp>
1878 } // namespace default_ops
1881 // Default versions of floating point classification routines:
1883 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1884 inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1886 using multiprecision::default_ops::eval_fpclassify;
1887 return eval_fpclassify(arg.backend());
1889 template <class tag, class A1, class A2, class A3, class A4>
1890 inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1892 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1893 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1895 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1896 inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1898 int v = fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg);
1899 return (v != (int)FP_INFINITE) && (v != (int)FP_NAN);
1901 template <class tag, class A1, class A2, class A3, class A4>
1902 inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1904 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1905 return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1907 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1908 inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1910 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NAN;
1912 template <class tag, class A1, class A2, class A3, class A4>
1913 inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1915 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1916 return isnan BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1918 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1919 inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1921 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_INFINITE;
1923 template <class tag, class A1, class A2, class A3, class A4>
1924 inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1926 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1927 return isinf BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1929 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1930 inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1932 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NORMAL;
1934 template <class tag, class A1, class A2, class A3, class A4>
1935 inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1937 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1938 return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1941 // Default versions of sign manipulation functions, if individual backends can do better than this
1942 // (for example with signed zero), then they should overload these functions further:
1944 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1945 inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1949 template <class tag, class A1, class A2, class A3, class A4>
1950 inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1952 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1953 return sign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1956 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1957 inline BOOST_MP_CXX14_CONSTEXPR int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1959 using default_ops::eval_signbit;
1960 return eval_signbit(arg.backend());
1962 template <class tag, class A1, class A2, class A3, class A4>
1963 inline BOOST_MP_CXX14_CONSTEXPR int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1965 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1966 return signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1968 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1969 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1973 template <class tag, class A1, class A2, class A3, class A4>
1974 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1976 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1977 return changesign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1979 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1980 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
1982 return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? (boost::multiprecision::changesign)(a) : a;
1984 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
1985 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
1987 return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
1989 template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
1990 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
1992 return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
1994 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
1995 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
1997 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1998 return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
2003 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2004 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
2005 real(const multiprecision::number<Backend, ExpressionTemplates>& a)
2007 using default_ops::eval_real;
2008 typedef typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result_type;
2009 boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
2011 eval_real(result.backend(), a.backend());
2014 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2015 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
2016 imag(const multiprecision::number<Backend, ExpressionTemplates>& a)
2018 using default_ops::eval_imag;
2019 typedef typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result_type;
2020 boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
2022 eval_imag(result.backend(), a.backend());
2026 template <class tag, class A1, class A2, class A3, class A4>
2027 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2028 real(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2030 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2031 detail::scoped_default_precision<value_type> precision_guard(arg);
2032 return real(value_type(arg));
2035 template <class tag, class A1, class A2, class A3, class A4>
2036 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2037 imag(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2039 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2040 detail::scoped_default_precision<value_type> precision_guard(arg);
2041 return imag(value_type(arg));
2045 // Complex number functions, these are overloaded at the Backend level, we just provide the
2046 // expression template versions here, plus overloads for non-complex types:
2048 template <class T, expression_template_option ExpressionTemplates>
2049 inline BOOST_MP_CXX14_CONSTEXPR typename boost::lazy_enable_if_c<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates> > >::type
2050 abs(const number<T, ExpressionTemplates>& v)
2052 return BOOST_MP_MOVE(boost::math::hypot(real(v), imag(v)));
2054 template <class tag, class A1, class A2, class A3, class A4>
2055 inline BOOST_MP_CXX14_CONSTEXPR typename boost::lazy_enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex, component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type> >::type
2056 abs(const detail::expression<tag, A1, A2, A3, A4>& v)
2058 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2059 return BOOST_MP_MOVE(abs(static_cast<number_type>(v)));
2062 template <class T, expression_template_option ExpressionTemplates>
2063 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
2064 arg(const number<T, ExpressionTemplates>& v)
2066 return BOOST_MP_MOVE(atan2(imag(v), real(v)));
2068 template <class T, expression_template_option ExpressionTemplates>
2069 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
2070 arg(const number<T, ExpressionTemplates>&)
2074 template <class tag, class A1, class A2, class A3, class A4>
2075 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex || number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename scalar_result_from_possible_complex<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
2076 arg(const detail::expression<tag, A1, A2, A3, A4>& v)
2078 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2079 return BOOST_MP_MOVE(arg(static_cast<number_type>(v)));
2082 template <class T, expression_template_option ExpressionTemplates>
2083 inline BOOST_MP_CXX14_CONSTEXPR typename boost::lazy_enable_if_c<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates> > >::type
2084 norm(const number<T, ExpressionTemplates>& v)
2086 typename component_type<number<T, ExpressionTemplates> >::type a(real(v)), b(imag(v));
2087 return BOOST_MP_MOVE(a * a + b * b);
2089 template <class T, expression_template_option ExpressionTemplates>
2090 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<T>::value != number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
2091 norm(const number<T, ExpressionTemplates>& v)
2095 template <class tag, class A1, class A2, class A3, class A4>
2096 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2097 norm(const detail::expression<tag, A1, A2, A3, A4>& v)
2099 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2100 return BOOST_MP_MOVE(norm(static_cast<number_type>(v)));
2103 template <class Backend, expression_template_option ExpressionTemplates>
2104 BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r, number<Backend, ExpressionTemplates> const& theta)
2106 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2109 template <class tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
2110 BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
2111 typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
2112 polar(detail::expression<tag, A1, A2, A3, A4> const& r, number<Backend, ExpressionTemplates> const& theta)
2114 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2117 template <class Backend, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2118 BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
2119 typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
2120 polar(number<Backend, ExpressionTemplates> const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
2122 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2125 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2126 BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, typename detail::expression<tagb, A1b, A2b, A3b, A4b>::result_type>::value,
2127 typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
2128 polar(detail::expression<tag, A1, A2, A3, A4> const& r, detail::expression<tagb, A1b, A2b, A3b, A4b> const& theta)
2130 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type scalar_type;
2131 return typename complex_result_from_scalar<scalar_type>::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta)));
2134 // We also allow the first argument to polar to be an arithmetic type (probably a literal):
2136 template <class Scalar, class Backend, expression_template_option ExpressionTemplates>
2137 BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_arithmetic<Scalar>::value, typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
2138 polar(Scalar const& r, number<Backend, ExpressionTemplates> const& theta)
2140 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2143 template <class tag, class A1, class A2, class A3, class A4, class Scalar>
2144 BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_arithmetic<Scalar>::value,
2145 typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
2146 polar(Scalar const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
2148 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type scalar_type;
2149 return typename complex_result_from_scalar<scalar_type>::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta)));
2152 // Single argument overloads:
2154 template <class Backend, expression_template_option ExpressionTemplates>
2155 BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r)
2157 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(r);
2160 template <class tag, class A1, class A2, class A3, class A4>
2161 BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2162 polar(detail::expression<tag, A1, A2, A3, A4> const& r)
2164 return typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type(r);
2167 } // namespace multiprecision
2172 // Import Math functions here, so they can be found by Boost.Math:
2174 using boost::multiprecision::changesign;
2175 using boost::multiprecision::copysign;
2176 using boost::multiprecision::fpclassify;
2177 using boost::multiprecision::isfinite;
2178 using boost::multiprecision::isinf;
2179 using boost::multiprecision::isnan;
2180 using boost::multiprecision::isnormal;
2181 using boost::multiprecision::sign;
2182 using boost::multiprecision::signbit;
2186 namespace multiprecision {
2188 typedef ::boost::math::policies::policy<
2189 ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>,
2190 ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>,
2191 ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>,
2192 ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>,
2193 ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error> >
2196 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2197 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2199 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2201 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2202 return boost::math::asinh(arg, c99_error_policy());
2204 template <class tag, class A1, class A2, class A3, class A4>
2205 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2207 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2209 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2210 detail::scoped_default_precision<value_type> precision_guard(arg);
2211 return asinh(value_type(arg));
2213 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2214 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2216 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2218 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2219 return boost::math::acosh(arg, c99_error_policy());
2221 template <class tag, class A1, class A2, class A3, class A4>
2222 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2224 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2226 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2227 detail::scoped_default_precision<value_type> precision_guard(arg);
2228 return acosh(value_type(arg));
2230 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2231 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2233 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2235 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2236 return boost::math::atanh(arg, c99_error_policy());
2238 template <class tag, class A1, class A2, class A3, class A4>
2239 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2241 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2243 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2244 detail::scoped_default_precision<value_type> precision_guard(arg);
2245 return atanh(value_type(arg));
2247 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2248 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2250 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2251 return boost::math::cbrt(arg, c99_error_policy());
2253 template <class tag, class A1, class A2, class A3, class A4>
2254 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2256 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2257 detail::scoped_default_precision<value_type> precision_guard(arg);
2258 return cbrt(value_type(arg));
2260 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2261 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2263 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2264 return boost::math::erf(arg, c99_error_policy());
2266 template <class tag, class A1, class A2, class A3, class A4>
2267 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2269 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2270 detail::scoped_default_precision<value_type> precision_guard(arg);
2271 return erf(value_type(arg));
2273 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2274 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2276 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2277 return boost::math::erfc(arg, c99_error_policy());
2279 template <class tag, class A1, class A2, class A3, class A4>
2280 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2282 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2283 detail::scoped_default_precision<value_type> precision_guard(arg);
2284 return erfc(value_type(arg));
2286 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2287 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2289 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2290 return boost::math::expm1(arg, c99_error_policy());
2292 template <class tag, class A1, class A2, class A3, class A4>
2293 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2295 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2296 detail::scoped_default_precision<value_type> precision_guard(arg);
2297 return expm1(value_type(arg));
2299 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2300 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2302 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2303 multiprecision::number<Backend, ExpressionTemplates> result;
2304 result = boost::math::lgamma(arg, c99_error_policy());
2305 if ((boost::multiprecision::isnan)(result) && !(boost::multiprecision::isnan)(arg))
2307 result = std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::infinity();
2312 template <class tag, class A1, class A2, class A3, class A4>
2313 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2315 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2316 detail::scoped_default_precision<value_type> precision_guard(arg);
2317 return lgamma(value_type(arg));
2319 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2320 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2322 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2323 if ((arg == 0) && std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::has_infinity)
2328 return boost::math::tgamma(arg, c99_error_policy());
2330 template <class tag, class A1, class A2, class A3, class A4>
2331 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2333 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2334 detail::scoped_default_precision<value_type> precision_guard(arg);
2335 return tgamma(value_type(arg));
2338 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2339 inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2343 template <class tag, class A1, class A2, class A3, class A4>
2344 inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2348 #ifndef BOOST_NO_LONG_LONG
2349 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2350 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2352 return llround(arg);
2354 template <class tag, class A1, class A2, class A3, class A4>
2355 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2357 return llround(arg);
2360 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2361 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2363 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2364 return boost::math::log1p(arg, c99_error_policy());
2366 template <class tag, class A1, class A2, class A3, class A4>
2367 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2369 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2370 detail::scoped_default_precision<value_type> precision_guard(arg);
2371 return log1p(value_type(arg));
2374 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2375 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2377 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2378 return boost::math::nextafter(a, b, c99_error_policy());
2380 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2381 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
2383 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2384 return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
2386 template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
2387 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2389 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2390 return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
2392 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2393 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
2395 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2396 detail::scoped_default_precision<value_type> precision_guard(a, b);
2397 return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
2399 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2400 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2402 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2403 return boost::math::nextafter(a, b, c99_error_policy());
2405 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2406 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
2408 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2409 return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
2411 template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
2412 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2414 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2415 return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
2417 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2418 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
2420 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2421 detail::scoped_default_precision<value_type> precision_guard(a, b);
2422 return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
2425 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
2426 inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2428 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2429 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2430 using default_ops::eval_add;
2431 eval_add(result.backend(), a.backend(), b.backend());
2435 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
2436 inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2438 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2439 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2440 using default_ops::eval_subtract;
2441 eval_subtract(result.backend(), a.backend(), b.backend());
2445 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
2446 inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2448 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2449 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2450 using default_ops::eval_multiply;
2451 eval_multiply(result.backend(), a.backend(), b.backend());
2455 template <class B, expression_template_option ET, class I>
2456 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
2457 add(number<B, ET>& result, const I& a, const I& b)
2459 using default_ops::eval_add;
2460 typedef typename detail::canonical<I, B>::type canonical_type;
2461 eval_add(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2465 template <class B, expression_template_option ET, class I>
2466 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
2467 subtract(number<B, ET>& result, const I& a, const I& b)
2469 using default_ops::eval_subtract;
2470 typedef typename detail::canonical<I, B>::type canonical_type;
2471 eval_subtract(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2475 template <class B, expression_template_option ET, class I>
2476 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
2477 multiply(number<B, ET>& result, const I& a, const I& b)
2479 using default_ops::eval_multiply;
2480 typedef typename detail::canonical<I, B>::type canonical_type;
2481 eval_multiply(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2485 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2486 inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<tag, A1, A2, A3, A4>::result_type trunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2488 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2489 return BOOST_MP_MOVE(trunc(number_type(v), pol));
2492 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
2493 inline BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates> trunc(const number<Backend, ExpressionTemplates>& v, const Policy&)
2495 using default_ops::eval_trunc;
2496 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(v);
2497 number<Backend, ExpressionTemplates> result;
2498 eval_trunc(result.backend(), v.backend());
2502 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2503 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2505 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2506 number_type r(trunc(v, pol));
2507 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
2508 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, number_type(v), 0, pol);
2509 return r.template convert_to<int>();
2511 template <class tag, class A1, class A2, class A3, class A4>
2512 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2514 return itrunc(v, boost::math::policies::policy<>());
2516 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
2517 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v, const Policy& pol)
2519 number<Backend, ExpressionTemplates> r(trunc(v, pol));
2520 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
2521 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol);
2522 return r.template convert_to<int>();
2524 template <class Backend, expression_template_option ExpressionTemplates>
2525 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v)
2527 return itrunc(v, boost::math::policies::policy<>());
2529 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2530 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2532 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2533 number_type r(trunc(v, pol));
2534 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
2535 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, number_type(v), 0L, pol);
2536 return r.template convert_to<long>();
2538 template <class tag, class A1, class A2, class A3, class A4>
2539 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2541 return ltrunc(v, boost::math::policies::policy<>());
2543 template <class T, expression_template_option ExpressionTemplates, class Policy>
2544 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
2546 number<T, ExpressionTemplates> r(trunc(v, pol));
2547 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
2548 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol);
2549 return r.template convert_to<long>();
2551 template <class T, expression_template_option ExpressionTemplates>
2552 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v)
2554 return ltrunc(v, boost::math::policies::policy<>());
2556 #ifndef BOOST_NO_LONG_LONG
2557 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2558 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2560 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2561 number_type r(trunc(v, pol));
2562 if ((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
2563 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, pol);
2564 return r.template convert_to<boost::long_long_type>();
2566 template <class tag, class A1, class A2, class A3, class A4>
2567 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2569 return lltrunc(v, boost::math::policies::policy<>());
2571 template <class T, expression_template_option ExpressionTemplates, class Policy>
2572 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
2574 number<T, ExpressionTemplates> r(trunc(v, pol));
2575 if ((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
2576 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol);
2577 return r.template convert_to<boost::long_long_type>();
2579 template <class T, expression_template_option ExpressionTemplates>
2580 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type lltrunc(const number<T, ExpressionTemplates>& v)
2582 return lltrunc(v, boost::math::policies::policy<>());
2585 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2586 inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<tag, A1, A2, A3, A4>::result_type round(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2588 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2589 return BOOST_MP_MOVE(round(static_cast<number_type>(v), pol));
2591 template <class T, expression_template_option ExpressionTemplates, class Policy>
2592 inline BOOST_MP_CXX14_CONSTEXPR number<T, ExpressionTemplates> round(const number<T, ExpressionTemplates>& v, const Policy&)
2594 using default_ops::eval_round;
2595 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2596 number<T, ExpressionTemplates> result;
2597 eval_round(result.backend(), v.backend());
2601 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2602 inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2604 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2605 number_type r(round(v, pol));
2606 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
2607 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0, pol);
2608 return r.template convert_to<int>();
2610 template <class tag, class A1, class A2, class A3, class A4>
2611 inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v)
2613 return iround(v, boost::math::policies::policy<>());
2615 template <class T, expression_template_option ExpressionTemplates, class Policy>
2616 inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v, const Policy& pol)
2618 number<T, ExpressionTemplates> r(round(v, pol));
2619 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
2620 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol);
2621 return r.template convert_to<int>();
2623 template <class T, expression_template_option ExpressionTemplates>
2624 inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v)
2626 return iround(v, boost::math::policies::policy<>());
2628 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2629 inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2631 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2632 number_type r(round(v, pol));
2633 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
2634 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, number_type(v), 0L, pol);
2635 return r.template convert_to<long>();
2637 template <class tag, class A1, class A2, class A3, class A4>
2638 inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v)
2640 return lround(v, boost::math::policies::policy<>());
2642 template <class T, expression_template_option ExpressionTemplates, class Policy>
2643 inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v, const Policy& pol)
2645 number<T, ExpressionTemplates> r(round(v, pol));
2646 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
2647 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol);
2648 return r.template convert_to<long>();
2650 template <class T, expression_template_option ExpressionTemplates>
2651 inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v)
2653 return lround(v, boost::math::policies::policy<>());
2655 #ifndef BOOST_NO_LONG_LONG
2656 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2657 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2659 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2660 number_type r(round(v, pol));
2661 if ((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
2662 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol);
2663 return r.template convert_to<boost::long_long_type>();
2665 template <class tag, class A1, class A2, class A3, class A4>
2666 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llround(const detail::expression<tag, A1, A2, A3, A4>& v)
2668 return llround(v, boost::math::policies::policy<>());
2670 template <class T, expression_template_option ExpressionTemplates, class Policy>
2671 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
2673 number<T, ExpressionTemplates> r(round(v, pol));
2674 if ((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
2675 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol);
2676 return r.template convert_to<boost::long_long_type>();
2678 template <class T, expression_template_option ExpressionTemplates>
2679 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llround(const number<T, ExpressionTemplates>& v)
2681 return llround(v, boost::math::policies::policy<>());
2685 // frexp does not return an expression template since we require the
2686 // integer argument to be evaluated even if the returned value is
2687 // not assigned to anything...
2689 template <class T, expression_template_option ExpressionTemplates>
2690 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, short* pint)
2692 using default_ops::eval_frexp;
2693 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2694 number<T, ExpressionTemplates> result;
2695 eval_frexp(result.backend(), v.backend(), pint);
2698 template <class tag, class A1, class A2, class A3, class A4>
2699 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2700 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, short* pint)
2702 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2703 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
2705 template <class T, expression_template_option ExpressionTemplates>
2706 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, int* pint)
2708 using default_ops::eval_frexp;
2709 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2710 number<T, ExpressionTemplates> result;
2711 eval_frexp(result.backend(), v.backend(), pint);
2714 template <class tag, class A1, class A2, class A3, class A4>
2715 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2716 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, int* pint)
2718 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2719 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
2721 template <class T, expression_template_option ExpressionTemplates>
2722 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long* pint)
2724 using default_ops::eval_frexp;
2725 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2726 number<T, ExpressionTemplates> result;
2727 eval_frexp(result.backend(), v.backend(), pint);
2730 template <class tag, class A1, class A2, class A3, class A4>
2731 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2732 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long* pint)
2734 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2735 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
2737 template <class T, expression_template_option ExpressionTemplates>
2738 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, boost::long_long_type* pint)
2740 using default_ops::eval_frexp;
2741 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2742 number<T, ExpressionTemplates> result;
2743 eval_frexp(result.backend(), v.backend(), pint);
2746 template <class tag, class A1, class A2, class A3, class A4>
2747 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2748 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, boost::long_long_type* pint)
2750 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2751 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
2754 // modf does not return an expression template since we require the
2755 // second argument to be evaluated even if the returned value is
2756 // not assigned to anything...
2758 template <class T, expression_template_option ExpressionTemplates>
2759 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const number<T, ExpressionTemplates>& v, number<T, ExpressionTemplates>* pipart)
2761 using default_ops::eval_modf;
2762 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2763 number<T, ExpressionTemplates> result;
2764 eval_modf(result.backend(), v.backend(), pipart ? &pipart->backend() : 0);
2767 template <class T, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2768 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const detail::expression<tag, A1, A2, A3, A4>& v, number<T, ExpressionTemplates>* pipart)
2770 using default_ops::eval_modf;
2771 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2772 number<T, ExpressionTemplates> result, arg(v);
2773 eval_modf(result.backend(), arg.backend(), pipart ? &pipart->backend() : 0);
2778 // Integer square root:
2780 template <class B, expression_template_option ExpressionTemplates>
2781 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
2782 sqrt(const number<B, ExpressionTemplates>& x)
2784 using default_ops::eval_integer_sqrt;
2785 number<B, ExpressionTemplates> s, r;
2786 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
2793 namespace default_ops {
2797 template <class B, class T, class U, class V>
2798 BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, const V& c) const
2800 eval_multiply_add(result, a, b, c);
2804 } // namespace default_ops
2806 template <class Backend, class U, class V>
2807 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2809 mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
2812 is_number_expression<U>,
2816 is_number_expression<V>,
2817 is_arithmetic<V> > >,
2818 detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V> >::type
2819 fma(const number<Backend, et_on>& a, const U& b, const V& c)
2821 return detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V>(
2822 default_ops::fma_func(), a, b, c);
2825 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U, class V>
2826 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2828 mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point>,
2831 is_number_expression<U>,
2835 is_number_expression<V>,
2836 is_arithmetic<V> > >,
2837 detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V> >::type
2838 fma(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, const V& c)
2840 return detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V>(
2841 default_ops::fma_func(), a, b, c);
2844 template <class Backend, class U, class V>
2845 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2847 mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
2850 is_number_expression<U>,
2854 is_number_expression<V>,
2855 is_arithmetic<V> > >,
2856 number<Backend, et_off> >::type
2857 fma(const number<Backend, et_off>& a, const U& b, const V& c)
2859 using default_ops::eval_multiply_add;
2860 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
2861 number<Backend, et_off> result;
2862 eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
2866 template <class U, class Backend, class V>
2867 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2869 mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
2873 is_number_expression<V>,
2874 is_arithmetic<V> > >,
2875 detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V> >::type
2876 fma(const U& a, const number<Backend, et_on>& b, const V& c)
2878 return detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V>(
2879 default_ops::fma_func(), a, b, c);
2882 template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
2883 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2885 mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point>,
2889 is_number_expression<V>,
2890 is_arithmetic<V> > >,
2891 detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
2892 fma(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, const V& c)
2894 return detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(
2895 default_ops::fma_func(), a, b, c);
2898 template <class U, class Backend, class V>
2899 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2901 mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
2905 is_number_expression<V>,
2906 is_arithmetic<V> > >,
2907 number<Backend, et_off> >::type
2908 fma(const U& a, const number<Backend, et_off>& b, const V& c)
2910 using default_ops::eval_multiply_add;
2911 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
2912 number<Backend, et_off> result;
2913 eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
2917 template <class U, class V, class Backend>
2918 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2920 mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
2923 detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> > >::type
2924 fma(const U& a, const V& b, const number<Backend, et_on>& c)
2926 return detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> >(
2927 default_ops::fma_func(), a, b, c);
2930 template <class U, class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
2931 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2933 mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point>,
2936 detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
2937 fma(const U& a, const V& b, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& c)
2939 return detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(
2940 default_ops::fma_func(), a, b, c);
2943 template <class U, class V, class Backend>
2944 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2946 mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
2949 number<Backend, et_off> >::type
2950 fma(const U& a, const V& b, const number<Backend, et_off>& c)
2952 using default_ops::eval_multiply_add;
2953 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
2954 number<Backend, et_off> result;
2955 eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
2959 namespace default_ops {
2963 template <class B, class T, class U>
2964 BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, int* pi) const
2966 eval_remquo(result, a, b, pi);
2970 } // namespace default_ops
2972 template <class Backend, class U>
2973 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
2974 number_category<number<Backend, et_on> >::value == number_kind_floating_point,
2975 detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*> >::type
2976 remquo(const number<Backend, et_on>& a, const U& b, int* pi)
2978 return detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*>(
2979 default_ops::remquo_func(), a, b, pi);
2982 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U>
2983 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
2984 number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point,
2985 detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*> >::type
2986 remquo(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, int* pi)
2988 return detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*>(
2989 default_ops::remquo_func(), a, b, pi);
2992 template <class U, class Backend>
2993 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
2994 (number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
2995 detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*> >::type
2996 remquo(const U& a, const number<Backend, et_on>& b, int* pi)
2998 return detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*>(
2999 default_ops::remquo_func(), a, b, pi);
3002 template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
3003 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
3004 (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
3005 detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*> >::type
3006 remquo(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, int* pi)
3008 return detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*>(
3009 default_ops::remquo_func(), a, b, pi);
3012 template <class Backend, class U>
3013 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
3014 number_category<number<Backend, et_on> >::value == number_kind_floating_point,
3015 number<Backend, et_off> >::type
3016 remquo(const number<Backend, et_off>& a, const U& b, int* pi)
3018 using default_ops::eval_remquo;
3019 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
3020 number<Backend, et_off> result;
3021 eval_remquo(result.backend(), a.backend(), number<Backend, et_off>::canonical_value(b), pi);
3024 template <class U, class Backend>
3025 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
3026 (number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
3027 number<Backend, et_off> >::type
3028 remquo(const U& a, const number<Backend, et_off>& b, int* pi)
3030 using default_ops::eval_remquo;
3031 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
3032 number<Backend, et_off> result;
3033 eval_remquo(result.backend(), number<Backend, et_off>::canonical_value(a), b.backend(), pi);
3037 template <class B, expression_template_option ExpressionTemplates>
3038 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
3039 sqrt(const number<B, ExpressionTemplates>& x, number<B, ExpressionTemplates>& r)
3041 using default_ops::eval_integer_sqrt;
3042 detail::scoped_default_precision<multiprecision::number<B, ExpressionTemplates> > precision_guard(x, r);
3043 number<B, ExpressionTemplates> s;
3044 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
3049 #define UNARY_OP_FUNCTOR(func, category) \
3050 namespace detail { \
3051 template <class Backend> \
3052 struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3054 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const \
3056 using default_ops::BOOST_JOIN(eval_, func); \
3057 BOOST_JOIN(eval_, func) \
3060 template <class U> \
3061 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg) const \
3063 using default_ops::BOOST_JOIN(eval_, func); \
3065 BOOST_JOIN(eval_, func) \
3072 template <class tag, class A1, class A2, class A3, class A4> \
3073 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category, \
3074 detail::expression< \
3075 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3076 detail::expression<tag, A1, A2, A3, A4> > > ::type \
3077 func(const detail::expression<tag, A1, A2, A3, A4>& arg) \
3079 return detail::expression< \
3080 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3081 detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg); \
3083 template <class Backend> \
3084 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<Backend>::value == category, \
3085 detail::expression< \
3086 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3087 number<Backend, et_on> > > ::type \
3088 func(const number<Backend, et_on>& arg) \
3090 return detail::expression< \
3091 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3092 number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg); \
3094 template <class Backend> \
3095 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c< \
3096 boost::multiprecision::number_category<Backend>::value == category, \
3097 number<Backend, et_off> >::type \
3098 func(const number<Backend, et_off>& arg) \
3100 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3101 number<Backend, et_off> result; \
3102 using default_ops::BOOST_JOIN(eval_, func); \
3103 BOOST_JOIN(eval_, func) \
3104 (result.backend(), arg.backend()); \
3108 #define BINARY_OP_FUNCTOR(func, category) \
3109 namespace detail { \
3110 template <class Backend> \
3111 struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3113 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg, const Backend& a) const \
3115 using default_ops::BOOST_JOIN(eval_, func); \
3116 BOOST_JOIN(eval_, func) \
3119 template <class Arithmetic> \
3120 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg, const Arithmetic& a) const \
3122 using default_ops::BOOST_JOIN(eval_, func); \
3123 BOOST_JOIN(eval_, func) \
3124 (result, arg, number<Backend>::canonical_value(a)); \
3126 template <class Arithmetic> \
3127 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Arithmetic& arg, const Backend& a) const \
3129 using default_ops::BOOST_JOIN(eval_, func); \
3130 BOOST_JOIN(eval_, func) \
3131 (result, number<Backend>::canonical_value(arg), a); \
3133 template <class U> \
3134 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg, const Backend& a) const \
3136 using default_ops::BOOST_JOIN(eval_, func); \
3138 BOOST_JOIN(eval_, func) \
3142 template <class U, class Arithmetic> \
3143 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg, const Arithmetic& a) const \
3145 using default_ops::BOOST_JOIN(eval_, func); \
3147 BOOST_JOIN(eval_, func) \
3148 (r, arg, number<Backend>::canonical_value(a)); \
3151 template <class U, class Arithmetic> \
3152 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Arithmetic& arg, const Backend& a) const \
3154 using default_ops::BOOST_JOIN(eval_, func); \
3156 BOOST_JOIN(eval_, func) \
3157 (r, number<Backend>::canonical_value(arg), a); \
3162 template <class Backend> \
3163 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<Backend>::value == category, \
3164 detail::expression< \
3165 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3166 number<Backend, et_on>, number<Backend, et_on> > > ::type \
3167 func(const number<Backend, et_on>& arg, const number<Backend, et_on>& a) \
3169 return detail::expression< \
3170 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3171 number<Backend, et_on>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3173 template <class Backend, class tag, class A1, class A2, class A3, class A4> \
3174 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3175 (number_category<Backend>::value == category) && (boost::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3176 detail::expression< \
3177 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3178 number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > > ::type \
3179 func(const number<Backend, et_on>& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
3181 return detail::expression< \
3182 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3183 number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3185 template <class tag, class A1, class A2, class A3, class A4, class Backend> \
3186 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3187 (number_category<Backend>::value == category) && (boost::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3188 detail::expression< \
3189 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3190 detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > > ::type \
3191 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const number<Backend, et_on>& a) \
3193 return detail::expression< \
3194 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3195 detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3197 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> \
3198 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3199 (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category) && (number_category<detail::expression<tagb, A1b, A2b, A3b, A4b> >::value == category), \
3200 detail::expression< \
3201 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3202 detail::expression<tag, A1, A2, A3, A4>, detail::expression<tagb, A1b, A2b, A3b, A4b> > > ::type \
3203 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const detail::expression<tagb, A1b, A2b, A3b, A4b>& a) \
3205 return detail::expression< \
3206 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3207 detail::expression<tag, A1, A2, A3, A4>, detail::expression<tagb, A1b, A2b, A3b, A4b> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
3209 template <class Backend, class Arithmetic> \
3210 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3211 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3212 detail::expression< \
3213 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3214 number<Backend, et_on>, Arithmetic> > ::type \
3215 func(const number<Backend, et_on>& arg, const Arithmetic& a) \
3217 return detail::expression< \
3218 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3219 number<Backend, et_on>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3221 template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
3222 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3223 is_compatible_arithmetic_type<Arithmetic, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
3224 detail::expression< \
3225 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3226 detail::expression<tag, A1, A2, A3, A4>, Arithmetic> > ::type \
3227 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const Arithmetic& a) \
3229 return detail::expression< \
3230 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3231 detail::expression<tag, A1, A2, A3, A4>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
3233 template <class Backend, class Arithmetic> \
3234 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3235 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3236 detail::expression< \
3237 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3238 Arithmetic, number<Backend, et_on> > > ::type \
3239 func(const Arithmetic& arg, const number<Backend, et_on>& a) \
3241 return detail::expression< \
3242 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3243 Arithmetic, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3245 template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
3246 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3247 is_compatible_arithmetic_type<Arithmetic, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
3248 detail::expression< \
3249 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3250 Arithmetic, detail::expression<tag, A1, A2, A3, A4> > > ::type \
3251 func(const Arithmetic& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
3253 return detail::expression< \
3254 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3255 Arithmetic, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
3257 template <class Backend> \
3258 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(number_category<Backend>::value == category), \
3259 number<Backend, et_off> >::type \
3260 func(const number<Backend, et_off>& arg, const number<Backend, et_off>& a) \
3262 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
3263 number<Backend, et_off> result; \
3264 using default_ops::BOOST_JOIN(eval_, func); \
3265 BOOST_JOIN(eval_, func) \
3266 (result.backend(), arg.backend(), a.backend()); \
3269 template <class Backend, class Arithmetic> \
3270 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3271 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
3272 number<Backend, et_off> >::type \
3273 func(const number<Backend, et_off>& arg, const Arithmetic& a) \
3275 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3276 number<Backend, et_off> result; \
3277 using default_ops::BOOST_JOIN(eval_, func); \
3278 BOOST_JOIN(eval_, func) \
3279 (result.backend(), arg.backend(), number<Backend, et_off>::canonical_value(a)); \
3282 template <class Backend, class Arithmetic> \
3283 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3284 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
3285 number<Backend, et_off> >::type \
3286 func(const Arithmetic& a, const number<Backend, et_off>& arg) \
3288 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3289 number<Backend, et_off> result; \
3290 using default_ops::BOOST_JOIN(eval_, func); \
3291 BOOST_JOIN(eval_, func) \
3292 (result.backend(), number<Backend, et_off>::canonical_value(a), arg.backend()); \
3296 #define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category) \
3297 template <class tag, class A1, class A2, class A3, class A4> \
3298 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3299 (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
3300 detail::expression< \
3301 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3302 detail::expression<tag, A1, A2, A3, A4>, Arg2> > ::type \
3303 func(const detail::expression<tag, A1, A2, A3, A4>& arg, Arg2 const& a) \
3305 return detail::expression< \
3306 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3307 detail::expression<tag, A1, A2, A3, A4>, Arg2 > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type > (), arg, a); \
3309 template <class Backend> \
3310 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3311 (number_category<Backend>::value == category), \
3312 detail::expression< \
3313 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3314 number<Backend, et_on>, Arg2> > ::type \
3315 func(const number<Backend, et_on>& arg, Arg2 const& a) \
3317 return detail::expression< \
3318 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3319 number<Backend, et_on>, Arg2 > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3321 template <class Backend> \
3322 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3323 (number_category<Backend>::value == category), \
3324 number<Backend, et_off> >::type \
3325 func(const number<Backend, et_off>& arg, Arg2 const& a) \
3327 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
3328 number<Backend, et_off> result; \
3329 using default_ops::BOOST_JOIN(eval_, func); \
3330 BOOST_JOIN(eval_, func) \
3331 (result.backend(), arg.backend(), a); \
3335 #define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category) \
3336 namespace detail { \
3337 template <class Backend> \
3338 struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3340 template <class Arg> \
3341 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, Backend const& arg, Arg a) const \
3343 using default_ops::BOOST_JOIN(eval_, func); \
3344 BOOST_JOIN(eval_, func) \
3350 HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)
3355 template <class Backend>
3358 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3360 using default_ops::eval_abs;
3361 eval_abs(result, arg);
3364 template <class Backend>
3367 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3369 using default_ops::eval_conj;
3370 eval_conj(result, arg);
3373 template <class Backend>
3376 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3378 using default_ops::eval_proj;
3379 eval_proj(result, arg);
3383 } // namespace detail
3385 template <class tag, class A1, class A2, class A3, class A4>
3386 inline BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex,
3388 detail::function, detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> > >::type
3389 abs(const detail::expression<tag, A1, A2, A3, A4>& arg)
3391 return detail::expression<
3392 detail::function, detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3393 detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3395 template <class Backend>
3396 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<number_category<Backend>::value == number_kind_complex,
3398 detail::function, detail::abs_funct<Backend>, number<Backend, et_on> > >::type
3399 abs(const number<Backend, et_on>& arg)
3401 return detail::expression<
3402 detail::function, detail::abs_funct<Backend>, number<Backend, et_on> >(
3403 detail::abs_funct<Backend>(), arg);
3405 template <class Backend>
3406 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<number_category<Backend>::value == number_kind_complex, number<Backend, et_off> >::type
3407 abs(const number<Backend, et_off>& arg)
3409 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3410 number<Backend, et_off> result;
3411 using default_ops::eval_abs;
3412 eval_abs(result.backend(), arg.backend());
3416 template <class tag, class A1, class A2, class A3, class A4>
3417 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3418 detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
3419 conj(const detail::expression<tag, A1, A2, A3, A4>& arg)
3421 return detail::expression<
3422 detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3423 detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3425 template <class Backend>
3426 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3427 detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >
3428 conj(const number<Backend, et_on>& arg)
3430 return detail::expression<
3431 detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >(
3432 detail::conj_funct<Backend>(), arg);
3434 template <class Backend>
3435 inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
3436 conj(const number<Backend, et_off>& arg)
3438 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3439 number<Backend, et_off> result;
3440 using default_ops::eval_conj;
3441 eval_conj(result.backend(), arg.backend());
3445 template <class tag, class A1, class A2, class A3, class A4>
3446 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3447 detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
3448 proj(const detail::expression<tag, A1, A2, A3, A4>& arg)
3450 return detail::expression<
3451 detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3452 detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3454 template <class Backend>
3455 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3456 detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >
3457 proj(const number<Backend, et_on>& arg)
3459 return detail::expression<
3460 detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >(
3461 detail::proj_funct<Backend>(), arg);
3463 template <class Backend>
3464 inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
3465 proj(const number<Backend, et_off>& arg)
3467 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3468 number<Backend, et_off> result;
3469 using default_ops::eval_proj;
3470 eval_proj(result.backend(), arg.backend());
3474 UNARY_OP_FUNCTOR(fabs, number_kind_floating_point)
3475 UNARY_OP_FUNCTOR(sqrt, number_kind_floating_point)
3476 UNARY_OP_FUNCTOR(floor, number_kind_floating_point)
3477 UNARY_OP_FUNCTOR(ceil, number_kind_floating_point)
3478 UNARY_OP_FUNCTOR(trunc, number_kind_floating_point)
3479 UNARY_OP_FUNCTOR(round, number_kind_floating_point)
3480 UNARY_OP_FUNCTOR(exp, number_kind_floating_point)
3481 UNARY_OP_FUNCTOR(exp2, number_kind_floating_point)
3482 UNARY_OP_FUNCTOR(log, number_kind_floating_point)
3483 UNARY_OP_FUNCTOR(log10, number_kind_floating_point)
3484 UNARY_OP_FUNCTOR(cos, number_kind_floating_point)
3485 UNARY_OP_FUNCTOR(sin, number_kind_floating_point)
3486 UNARY_OP_FUNCTOR(tan, number_kind_floating_point)
3487 UNARY_OP_FUNCTOR(asin, number_kind_floating_point)
3488 UNARY_OP_FUNCTOR(acos, number_kind_floating_point)
3489 UNARY_OP_FUNCTOR(atan, number_kind_floating_point)
3490 UNARY_OP_FUNCTOR(cosh, number_kind_floating_point)
3491 UNARY_OP_FUNCTOR(sinh, number_kind_floating_point)
3492 UNARY_OP_FUNCTOR(tanh, number_kind_floating_point)
3493 UNARY_OP_FUNCTOR(log2, number_kind_floating_point)
3494 UNARY_OP_FUNCTOR(nearbyint, number_kind_floating_point)
3495 UNARY_OP_FUNCTOR(rint, number_kind_floating_point)
3497 HETERO_BINARY_OP_FUNCTOR(ldexp, short, number_kind_floating_point)
3498 //HETERO_BINARY_OP_FUNCTOR(frexp, short*, number_kind_floating_point)
3499 HETERO_BINARY_OP_FUNCTOR_B(ldexp, int, number_kind_floating_point)
3500 //HETERO_BINARY_OP_FUNCTOR_B(frexp, int*, number_kind_floating_point)
3501 HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point)
3502 //HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point)
3503 HETERO_BINARY_OP_FUNCTOR_B(ldexp, boost::long_long_type, number_kind_floating_point)
3504 //HETERO_BINARY_OP_FUNCTOR_B(frexp, boost::long_long_type*, number_kind_floating_point)
3505 BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
3506 BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
3507 BINARY_OP_FUNCTOR(fmax, number_kind_floating_point)
3508 BINARY_OP_FUNCTOR(fmin, number_kind_floating_point)
3509 BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
3510 BINARY_OP_FUNCTOR(fdim, number_kind_floating_point)
3511 BINARY_OP_FUNCTOR(hypot, number_kind_floating_point)
3512 BINARY_OP_FUNCTOR(remainder, number_kind_floating_point)
3514 UNARY_OP_FUNCTOR(logb, number_kind_floating_point)
3515 HETERO_BINARY_OP_FUNCTOR(scalbn, short, number_kind_floating_point)
3516 HETERO_BINARY_OP_FUNCTOR(scalbln, short, number_kind_floating_point)
3517 HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point)
3518 HETERO_BINARY_OP_FUNCTOR_B(scalbln, int, number_kind_floating_point)
3519 HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point)
3520 HETERO_BINARY_OP_FUNCTOR_B(scalbln, long, number_kind_floating_point)
3521 HETERO_BINARY_OP_FUNCTOR_B(scalbn, boost::long_long_type, number_kind_floating_point)
3522 HETERO_BINARY_OP_FUNCTOR_B(scalbln, boost::long_long_type, number_kind_floating_point)
3525 // Complex functions:
3527 UNARY_OP_FUNCTOR(exp, number_kind_complex)
3528 UNARY_OP_FUNCTOR(log, number_kind_complex)
3529 UNARY_OP_FUNCTOR(log10, number_kind_complex)
3530 BINARY_OP_FUNCTOR(pow, number_kind_complex)
3531 UNARY_OP_FUNCTOR(sqrt, number_kind_complex)
3532 UNARY_OP_FUNCTOR(sin, number_kind_complex)
3533 UNARY_OP_FUNCTOR(cos, number_kind_complex)
3534 UNARY_OP_FUNCTOR(tan, number_kind_complex)
3535 UNARY_OP_FUNCTOR(asin, number_kind_complex)
3536 UNARY_OP_FUNCTOR(acos, number_kind_complex)
3537 UNARY_OP_FUNCTOR(atan, number_kind_complex)
3538 UNARY_OP_FUNCTOR(sinh, number_kind_complex)
3539 UNARY_OP_FUNCTOR(cosh, number_kind_complex)
3540 UNARY_OP_FUNCTOR(tanh, number_kind_complex)
3541 UNARY_OP_FUNCTOR(asinh, number_kind_complex)
3542 UNARY_OP_FUNCTOR(acosh, number_kind_complex)
3543 UNARY_OP_FUNCTOR(atanh, number_kind_complex)
3546 // Integer functions:
3548 BINARY_OP_FUNCTOR(gcd, number_kind_integer)
3549 BINARY_OP_FUNCTOR(lcm, number_kind_integer)
3550 HETERO_BINARY_OP_FUNCTOR(pow, unsigned, number_kind_integer)
3552 #undef BINARY_OP_FUNCTOR
3553 #undef UNARY_OP_FUNCTOR
3558 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
3559 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<Backend>::value == number_kind_floating_point, typename Backend::exponent_type>::type
3560 ilogb(const multiprecision::number<Backend, ExpressionTemplates>& val)
3562 using default_ops::eval_ilogb;
3563 return eval_ilogb(val.backend());
3566 template <class tag, class A1, class A2, class A3, class A4>
3567 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == number_kind_floating_point, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type::backend_type::exponent_type>::type
3568 ilogb(const detail::expression<tag, A1, A2, A3, A4>& val)
3570 using default_ops::eval_ilogb;
3571 typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type arg(val);
3572 return eval_ilogb(arg.backend());
3575 } //namespace multiprecision
3579 // Overload of Boost.Math functions that find the wrong overload when used with number:
3586 } // namespace detail
3587 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
3588 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
3590 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3591 return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
3594 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
3595 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
3597 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3598 return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
3601 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
3602 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
3604 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3605 return BOOST_MP_MOVE(detail::sinhc_pi_imp(x));
3608 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
3609 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
3611 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3612 return BOOST_MP_MOVE(boost::math::sinhc_pi(x));
3615 using boost::multiprecision::gcd;
3616 using boost::multiprecision::lcm;
3619 #pragma warning(pop)
3625 using boost::multiprecision::gcd;
3626 using boost::multiprecision::lcm;
3628 } // namespace integer
3630 } // namespace boost
3633 // This has to come last of all:
3635 #include <boost/multiprecision/detail/no_et_ops.hpp>
3636 #include <boost/multiprecision/detail/et_ops.hpp>
3638 // min/max overloads:
3640 #include <boost/multiprecision/detail/min_max.hpp>