1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright 2011-21 John Maddock.
3 // Copyright 2021 Iskandarov Lev. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 #ifndef BOOST_MATH_BIG_NUM_DEF_OPS
8 #define BOOST_MATH_BIG_NUM_DEF_OPS
10 #include <boost/multiprecision/detail/standalone_config.hpp>
11 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
12 #include <boost/multiprecision/detail/number_base.hpp>
13 #include <boost/multiprecision/detail/assert.hpp>
14 #include <boost/multiprecision/traits/is_backend.hpp>
15 #include <boost/multiprecision/detail/fpclassify.hpp>
18 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
19 #include <string_view>
22 #ifdef BOOST_MP_MATH_AVAILABLE
23 #include <boost/math/special_functions/fpclassify.hpp>
24 #include <boost/math/special_functions/next.hpp>
25 #include <boost/math/special_functions/hypot.hpp>
26 #include <boost/math/policies/error_handling.hpp>
29 #ifndef INSTRUMENT_BACKEND
30 #ifndef BOOST_MP_INSTRUMENT
31 #define INSTRUMENT_BACKEND(x)
33 #define INSTRUMENT_BACKEND(x) \
34 std::cout << BOOST_STRINGIZE(x) << " = " << x.str(0, std::ios_base::scientific) << std::endl;
39 namespace multiprecision {
43 template <class To, class From>
44 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
45 template <class To, class From>
46 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_integer>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
47 template <class To, class From>
48 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_floating_point>& /*to_type*/, const std::integral_constant<int, number_kind_floating_point>& /*from_type*/);
49 template <class To, class From>
50 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_rational>& /*from_type*/);
51 template <class To, class From>
52 void generic_interconvert(To& to, const From& from, const std::integral_constant<int, number_kind_rational>& /*to_type*/, const std::integral_constant<int, number_kind_integer>& /*from_type*/);
54 template <class Integer>
55 BOOST_MP_CXX14_CONSTEXPR Integer karatsuba_sqrt(const Integer& x, Integer& r, size_t bits);
59 namespace default_ops {
62 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val);
65 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val) { return val < 0; }
67 inline int eval_signbit(float val) { return (std::signbit)(val); }
68 inline int eval_signbit(double val) { return (std::signbit)(val); }
69 inline int eval_signbit(long double val) { return (std::signbit)(val); }
70 #ifdef BOOST_HAS_FLOAT128
71 extern "C" int signbitq(float128_type) throw();
72 inline int eval_signbit(float128_type val) { return signbitq(val); }
76 BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const T& val);
79 // warning C4127: conditional expression is constant
80 // warning C4146: unary minus operator applied to unsigned type, result still unsigned
82 #pragma warning(disable : 4127 4146)
85 // Default versions of mixed arithmetic, these just construct a temporary
86 // from the arithmetic value and then do the arithmetic on that, two versions
87 // of each depending on whether the backend can be directly constructed from type V.
89 // Note that we have to provide *all* the template parameters to class number when used in
90 // enable_if as MSVC-10 won't compile the code if we rely on a computed-default parameter.
91 // Since the result of the test doesn't depend on whether expression templates are on or off
92 // we just use et_on everywhere. We could use a BOOST_WORKAROUND but that just obfuscates the
95 template <class T, class V>
96 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
97 eval_add(T& result, V const& v)
103 template <class T, class V>
104 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
105 eval_add(T& result, V const& v)
110 template <class T, class V>
111 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
112 eval_subtract(T& result, V const& v)
116 eval_subtract(result, t);
118 template <class T, class V>
119 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
120 eval_subtract(T& result, V const& v)
123 eval_subtract(result, t);
125 template <class T, class V>
126 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<V, T>::value>::type
127 eval_multiply(T& result, V const& v)
131 eval_multiply(result, t);
133 template <class T, class V>
134 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, T>::value>::type
135 eval_multiply(T& result, V const& v)
138 eval_multiply(result, t);
141 template <class T, class U, class V>
142 BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v);
144 template <class T, class U, class V>
145 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_add(T& t, const U& u, const V& v)
148 eval_multiply(z, u, v);
151 template <class T, class U, class V>
152 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
154 eval_multiply_add(t, v, u);
156 template <class T, class U, class V>
157 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_subtract(T& t, const U& u, const V& v)
160 eval_multiply(z, u, v);
163 template <class T, class U, class V>
164 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
166 eval_multiply_subtract(t, v, u);
168 template <class T, class V>
169 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
170 eval_divide(T& result, V const& v)
174 eval_divide(result, t);
176 template <class T, class V>
177 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
178 eval_divide(T& result, V const& v)
181 eval_divide(result, t);
183 template <class T, class V>
184 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
185 eval_modulus(T& result, V const& v)
189 eval_modulus(result, t);
191 template <class T, class V>
192 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
193 eval_modulus(T& result, V const& v)
196 eval_modulus(result, t);
198 template <class T, class V>
199 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
200 eval_bitwise_and(T& result, V const& v)
204 eval_bitwise_and(result, t);
206 template <class T, class V>
207 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
208 eval_bitwise_and(T& result, V const& v)
211 eval_bitwise_and(result, t);
213 template <class T, class V>
214 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
215 eval_bitwise_or(T& result, V const& v)
219 eval_bitwise_or(result, t);
221 template <class T, class V>
222 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
223 eval_bitwise_or(T& result, V const& v)
226 eval_bitwise_or(result, t);
228 template <class T, class V>
229 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
230 eval_bitwise_xor(T& result, V const& v)
234 eval_bitwise_xor(result, t);
236 template <class T, class V>
237 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
238 eval_bitwise_xor(T& result, V const& v)
241 eval_bitwise_xor(result, t);
244 template <class T, class V>
245 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && !std::is_convertible<V, T>::value>::type
246 eval_complement(T& result, V const& v)
250 eval_complement(result, t);
252 template <class T, class V>
253 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<V, number<T, et_on> >::value && std::is_convertible<V, T>::value>::type
254 eval_complement(T& result, V const& v)
257 eval_complement(result, t);
261 // Default versions of 3-arg arithmetic functions, these mostly just forward to the 2 arg versions:
263 template <class T, class U, class V>
264 BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v);
267 inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const T& u, const T& v)
283 template <class T, class U>
284 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
290 template <class T, class U>
291 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
296 template <class T, class U>
297 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_add_default(T& t, const U& u, const T& v)
301 template <class T, class U, class V>
302 inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const U& u, const V& v)
304 BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
306 if ((void*)&t == (void*)&v)
322 template <class T, class U, class V>
323 inline BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v)
325 eval_add_default(t, u, v);
328 template <class T, class U, class V>
329 void BOOST_MP_CXX14_CONSTEXPR eval_subtract(T& t, const U& u, const V& v);
332 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const T& u, const T& v)
334 if ((&t == &v) && is_signed_number<T>::value)
349 template <class T, class U>
350 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
354 eval_subtract(t, u, vv);
356 template <class T, class U>
357 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
360 eval_subtract(t, u, vv);
362 template <class T, class U>
363 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value && (number_category<T>::value != number_kind_complex)>::type eval_subtract_default(T& t, const U& u, const T& v)
365 eval_subtract(t, v, u);
366 if(!eval_is_zero(t) || (eval_signbit(u) != eval_signbit(v)))
369 template <class T, class U>
370 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value && (number_category<T>::value == number_kind_complex)>::type eval_subtract_default(T& t, const U& u, const T& v)
372 eval_subtract(t, v, u);
375 template <class T, class U>
376 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
380 eval_subtract(t, temp, v);
382 template <class T, class U>
383 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
386 eval_subtract(t, temp, v);
388 template <class T, class U, class V>
389 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const U& u, const V& v)
391 BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
393 if ((void*)&t == (void*)&v)
410 template <class T, class U, class V>
411 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(T& t, const U& u, const V& v)
413 eval_subtract_default(t, u, v);
417 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const T& u, const T& v)
433 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
434 template <class T, class U>
435 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
439 eval_multiply(t, u, vv);
441 template <class T, class U>
442 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
445 eval_multiply(t, u, vv);
447 template <class T, class U>
448 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_multiply_default(T& t, const U& u, const T& v)
450 eval_multiply(t, v, u);
453 template <class T, class U, class V>
454 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const U& u, const V& v)
456 BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
458 if ((void*)&t == (void*)&v)
464 t = number<T>::canonical_value(u);
470 t = number<T>::canonical_value(u);
474 template <class T, class U, class V>
475 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v)
477 eval_multiply_default(t, u, v);
481 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_add(T& t, const T& u, const T& v, const T& x)
483 if ((void*)&x == (void*)&t)
486 z = number<T>::canonical_value(x);
487 eval_multiply_add(t, u, v, z);
491 eval_multiply(t, u, v);
496 template <class T, class U>
497 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_same<T, U>::value, T>::type make_T(const U& u)
500 t = number<T>::canonical_value(u);
504 inline BOOST_MP_CXX14_CONSTEXPR const T& make_T(const T& t)
509 template <class T, class U, class V, class X>
510 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
512 eval_multiply_add(t, make_T<T>(u), make_T<T>(v), make_T<T>(x));
514 template <class T, class U, class V, class X>
515 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
517 eval_multiply_add(t, v, u, x);
519 template <class T, class U, class V, class X>
520 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!(!std::is_same<T, U>::value && std::is_same<T, V>::value)>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
522 if ((void*)&x == (void*)&t)
526 eval_multiply_subtract(t, u, v, z);
530 eval_multiply(t, u, v);
534 template <class T, class U, class V, class X>
535 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value && std::is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
537 eval_multiply_subtract(t, v, u, x);
540 template <class T, class U, class V>
541 BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v);
544 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const T& u, const T& v)
551 eval_divide(temp, u, v);
560 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
561 template <class T, class U>
562 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
566 eval_divide(t, u, vv);
568 template <class T, class U>
569 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
572 eval_divide(t, u, vv);
574 template <class T, class U>
575 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
579 eval_divide(t, uu, v);
581 template <class T, class U>
582 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
585 eval_divide(t, uu, v);
588 template <class T, class U, class V>
589 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const U& u, const V& v)
591 BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
593 if ((void*)&t == (void*)&v)
597 eval_divide(temp, v);
612 template <class T, class U, class V>
613 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v)
615 eval_divide_default(t, u, v);
618 template <class T, class U, class V>
619 BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v);
622 inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const T& u, const T& v)
629 eval_modulus(temp, u, v);
638 template <class T, class U>
639 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
643 eval_modulus(t, u, vv);
645 template <class T, class U>
646 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
649 eval_modulus(t, u, vv);
651 template <class T, class U>
652 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
656 eval_modulus(t, uu, v);
658 template <class T, class U>
659 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
662 eval_modulus(t, uu, v);
664 template <class T, class U, class V>
665 inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const U& u, const V& v)
667 BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
669 if ((void*)&t == (void*)&v)
672 eval_modulus(temp, v);
687 template <class T, class U, class V>
688 inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v)
690 eval_modulus_default(t, u, v);
693 template <class T, class U, class V>
694 BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v);
697 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and_default(T& t, const T& u, const T& v)
701 eval_bitwise_and(t, u);
705 eval_bitwise_and(t, v);
710 eval_bitwise_and(t, v);
713 template <class T, class U>
714 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !std::is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
718 eval_bitwise_and(t, u, vv);
720 template <class T, class U>
721 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
724 eval_bitwise_and(t, u, vv);
726 template <class T, class U>
727 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v)
729 eval_bitwise_and(t, v, u);
731 template <class T, class U, class V>
732 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!std::is_same<T, U>::value || std::is_same<T, V>::value>::type eval_bitwise_and_default(T& t, const U& u, const V& v)
735 eval_bitwise_and(t, v);
737 template <class T, class U, class V>
738 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v)
740 eval_bitwise_and_default(t, u, v);
743 template <class T, class U, class V>
744 BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v);
747 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const T& u, const T& v)
751 eval_bitwise_or(t, u);
755 eval_bitwise_or(t, v);
760 eval_bitwise_or(t, v);
763 template <class T, class U>
764 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
768 eval_bitwise_or(t, u, vv);
770 template <class T, class U>
771 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
774 eval_bitwise_or(t, u, vv);
776 template <class T, class U>
777 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v)
779 eval_bitwise_or(t, v, u);
781 template <class T, class U, class V>
782 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const U& u, const V& v)
784 BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
786 if ((void*)&t == (void*)&v)
788 eval_bitwise_or(t, u);
793 eval_bitwise_or(t, v);
799 eval_bitwise_or(t, v);
802 template <class T, class U, class V>
803 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v)
805 eval_bitwise_or_default(t, u, v);
808 template <class T, class U, class V>
809 BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v);
812 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const T& u, const T& v)
816 eval_bitwise_xor(t, u);
820 eval_bitwise_xor(t, v);
825 eval_bitwise_xor(t, v);
828 template <class T, class U>
829 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && !std::is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
833 eval_bitwise_xor(t, u, vv);
835 template <class T, class U>
836 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value && std::is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
839 eval_bitwise_xor(t, u, vv);
841 template <class T, class U>
842 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v)
844 eval_bitwise_xor(t, v, u);
846 template <class T, class U, class V>
847 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const U& u, const V& v)
849 BOOST_IF_CONSTEXPR(std::is_same<T, V>::value)
851 if ((void*)&t == (void*)&v)
853 eval_bitwise_xor(t, u);
858 eval_bitwise_xor(t, v);
864 eval_bitwise_xor(t, v);
867 template <class T, class U, class V>
868 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v)
870 eval_bitwise_xor_default(t, u, v);
874 inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(T& val)
876 using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
877 eval_add(val, static_cast<ui_type>(1u));
880 inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(T& val)
882 using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
883 eval_subtract(val, static_cast<ui_type>(1u));
886 template <class T, class U, class V>
887 inline BOOST_MP_CXX14_CONSTEXPR void eval_left_shift(T& result, const U& arg, const V val)
890 eval_left_shift(result, val);
893 template <class T, class U, class V>
894 inline BOOST_MP_CXX14_CONSTEXPR void eval_right_shift(T& result, const U& arg, const V val)
897 eval_right_shift(result, val);
901 inline BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const T& val)
903 using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
904 return val.compare(static_cast<ui_type>(0)) == 0;
907 inline BOOST_MP_CXX14_CONSTEXPR int eval_get_sign(const T& val)
909 using ui_type = typename std::tuple_element<0, typename T::unsigned_types>::type;
910 return val.compare(static_cast<ui_type>(0));
913 template <class T, class V, class U>
914 inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::false_type&, const std::false_type&)
916 using component_number_type = typename component_type<number<T> >::type;
918 boost::multiprecision::detail::scoped_precision_options<component_number_type> sp(result);
921 component_number_type x(v1), y(v2);
922 assign_components(result, x.backend(), y.backend());
924 template <class T, class V, class U>
925 inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::true_type&, const std::false_type&)
927 boost::multiprecision::detail::scoped_source_precision<number<V>> scope;
929 assign_components_imp2(result, number<V>(v1), v2, std::false_type(), std::false_type());
931 template <class T, class V, class U>
932 inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::true_type&, const std::true_type&)
934 boost::multiprecision::detail::scoped_source_precision<number<V>> scope1;
935 boost::multiprecision::detail::scoped_source_precision<number<U>> scope2;
938 assign_components_imp2(result, number<V>(v1), number<U>(v2), std::false_type(), std::false_type());
940 template <class T, class V, class U>
941 inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp2(T& result, const V& v1, const U& v2, const std::false_type&, const std::true_type&)
943 boost::multiprecision::detail::scoped_source_precision<number<U>> scope;
945 assign_components_imp2(result, v1, number<U>(v2), std::false_type(), std::false_type());
949 template <class T, class V, class U>
950 inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const std::integral_constant<int, number_kind_rational>&)
955 eval_divide(result, t);
958 template <class T, class V, class U, int N>
959 inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const std::integral_constant<int, N>&)
961 assign_components_imp2(result, v1, v2, boost::multiprecision::detail::is_backend<V>(), boost::multiprecision::detail::is_backend<U>());
964 template <class T, class V, class U>
965 inline BOOST_MP_CXX14_CONSTEXPR void assign_components(T& result, const V& v1, const U& v2)
967 return assign_components_imp(result, v1, v2, typename number_category<T>::type());
969 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
970 template <class Result, class Traits>
971 inline void assign_from_string_view(Result& result, const std::basic_string_view<char, Traits>& view)
973 // since most (all?) backends require a const char* to construct from, we just
978 template <class Result, class Traits>
979 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)
981 // since most (all?) backends require a const char* to construct from, we just
983 std::string x(view_x), y(view_y);
984 assign_components(result, x.c_str(), y.c_str());
987 template <class R, int b>
988 struct has_enough_bits
991 struct type : public std::integral_constant<bool, !std::is_same<R, T>::value && (std::numeric_limits<T>::digits >= b)>
998 BOOST_MP_CXX14_CONSTEXPR terminal(const R& v) : value(v) {}
999 BOOST_MP_CXX14_CONSTEXPR terminal() {}
1000 BOOST_MP_CXX14_CONSTEXPR terminal& operator=(R val)
1006 BOOST_MP_CXX14_CONSTEXPR operator R() const { return value; }
1009 template <class Tuple, int i, class T, bool = (i == std::tuple_size<Tuple>::value)>
1010 struct find_index_of_type
1012 static constexpr int value =
1013 std::is_same<T, typename std::tuple_element<static_cast<std::size_t>(i), Tuple>::type>::value
1015 : find_index_of_type<Tuple, i + 1, T>::value;
1017 template <class Tuple, int i, class T>
1018 struct find_index_of_type<Tuple, i, T, true>
1020 static constexpr int value = -1;
1024 template <class R, class B>
1025 struct calculate_next_larger_type
1027 // Find which list we're looking through:
1028 using list_type = typename std::conditional<
1029 boost::multiprecision::detail::is_signed<R>::value && boost::multiprecision::detail::is_integral<R>::value,
1030 typename B::signed_types,
1031 typename std::conditional<
1032 boost::multiprecision::detail::is_unsigned<R>::value,
1033 typename B::unsigned_types,
1034 typename B::float_types>::type>::type;
1035 static constexpr int start = find_index_of_type<list_type, 0, R>::value;
1036 static constexpr int index_of_type = boost::multiprecision::detail::find_index_of_large_enough_type<list_type, start == INT_MAX ? 0 : start + 1, boost::multiprecision::detail::bits_of<R>::value> ::value;
1037 using type = typename boost::multiprecision::detail::dereference_tuple<index_of_type, list_type, terminal<R> >::type;
1040 template <class R, class T>
1041 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<R>::value, bool>::type check_in_range(const T& t)
1043 // Can t fit in an R?
1044 if ((t > 0) && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)()))
1050 template <class R, class B>
1051 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend)
1053 using next_type = typename calculate_next_larger_type<R, B>::type;
1054 next_type n = next_type();
1055 eval_convert_to(&n, backend);
1056 BOOST_IF_CONSTEXPR(!boost::multiprecision::detail::is_unsigned<R>::value && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded)
1058 if(n > (next_type)(std::numeric_limits<R>::max)())
1060 *result = (std::numeric_limits<R>::max)();
1064 BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized&& std::numeric_limits<R>::is_bounded)
1066 if (n < (next_type)(std::numeric_limits<R>::min)())
1068 *result = (std::numeric_limits<R>::min)();
1072 *result = static_cast<R>(n);
1075 template <class R, class B>
1076 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< !boost::multiprecision::detail::is_integral<R>::value && !std::is_enum<R>::value>::type eval_convert_to(R* result, const B& backend)
1078 using next_type = typename calculate_next_larger_type<R, B>::type;
1079 next_type n = next_type();
1080 eval_convert_to(&n, backend);
1081 BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded)
1083 if ((n > (next_type)(std::numeric_limits<R>::max)() || (n < (next_type) - (std::numeric_limits<R>::max)())))
1085 *result = n > 0 ? (std::numeric_limits<R>::max)() : -(std::numeric_limits<R>::max)();
1088 *result = static_cast<R>(n);
1091 *result = static_cast<R>(n);
1094 template <class R, class B>
1095 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_enum<R>::value>::type eval_convert_to(R* result, const B& backend)
1097 typename std::underlying_type<R>::type t{};
1098 eval_convert_to(&t, backend);
1099 *result = static_cast<R>(t);
1102 #ifndef BOOST_MP_STANDALONE
1103 template <class R, class B>
1104 inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, false>&)
1107 // We ran out of types to try for the conversion, try
1108 // a lexical_cast and hope for the best:
1110 BOOST_IF_CONSTEXPR (std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed)
1111 if (eval_get_sign(backend) < 0)
1112 BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
1114 result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0)));
1116 BOOST_MP_CATCH (const bad_lexical_cast&)
1118 if (eval_get_sign(backend) < 0)
1120 BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed)
1121 *result = (std::numeric_limits<R>::max)(); // we should never get here, exception above will be raised.
1122 else BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_integer)
1123 *result = (std::numeric_limits<R>::min)();
1125 *result = -(std::numeric_limits<R>::max)();
1128 *result = (std::numeric_limits<R>::max)();
1133 template <class R, class B>
1134 inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, true>&)
1137 // Last chance conversion to an unsigned integer.
1138 // We ran out of types to try for the conversion, try
1139 // a lexical_cast and hope for the best:
1141 if (eval_get_sign(backend) < 0)
1142 BOOST_MP_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
1145 R mask = ~static_cast<R>(0u);
1146 eval_bitwise_and(t, mask);
1147 result->value = boost::lexical_cast<R>(t.str(0, std::ios_base::fmtflags(0)));
1149 BOOST_MP_CATCH (const bad_lexical_cast&)
1151 // We should never really get here...
1152 *result = (std::numeric_limits<R>::max)();
1156 #else // Using standalone mode
1158 template <class R, class B>
1159 inline void last_chance_eval_convert_to(terminal<R>*, const B&, const std::integral_constant<bool, false>&)
1161 static_assert(sizeof(R) == 1, "This type can not be used in standalone mode. Please de-activate and file a bug at https://github.com/boostorg/multiprecision/");
1164 template <class R, class B>
1165 inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const std::integral_constant<bool, true>&)
1167 static_assert(sizeof(R) == 1, "This type can not be used in standalone mode. Please de-activate and file a bug at https://github.com/boostorg/multiprecision/");
1171 template <class R, class B>
1172 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<R>* result, const B& backend)
1174 using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_unsigned<R>::value && number_category<B>::value == number_kind_integer>;
1175 last_chance_eval_convert_to(result, backend, tag_type());
1178 template <class B1, class B2, expression_template_option et>
1179 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<number<B1, et> >* result, const B2& backend)
1182 // We ran out of types to try for the conversion, try
1183 // a generic conversion and hope for the best:
1185 boost::multiprecision::detail::generic_interconvert(result->value.backend(), backend, number_category<B1>(), number_category<B2>());
1189 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::string* result, const B& backend)
1191 *result = backend.str(0, std::ios_base::fmtflags(0));
1195 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<float>* result, const B& backend)
1197 using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
1199 eval_real(re.backend(), backend);
1200 eval_imag(im.backend(), backend);
1202 *result = std::complex<float>(re.template convert_to<float>(), im.template convert_to<float>());
1206 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<double>* result, const B& backend)
1208 using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
1210 eval_real(re.backend(), backend);
1211 eval_imag(im.backend(), backend);
1213 *result = std::complex<double>(re.template convert_to<double>(), im.template convert_to<double>());
1217 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<long double>* result, const B& backend)
1219 using scalar_type = typename scalar_result_from_possible_complex<multiprecision::number<B> >::type;
1221 eval_real(re.backend(), backend);
1222 eval_imag(im.backend(), backend);
1224 *result = std::complex<long double>(re.template convert_to<long double>(), im.template convert_to<long double>());
1230 template <class T, class U>
1231 inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(T& result, const U& arg)
1233 using type_list = typename U::signed_types ;
1234 using front = typename std::tuple_element<0, type_list>::type;
1236 if (arg.compare(front(0)) < 0)
1239 template <class T, class U>
1240 inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(T& result, const U& arg)
1242 static_assert(number_category<T>::value == number_kind_floating_point, "The fabs function is only valid for floating point types.");
1243 using type_list = typename U::signed_types ;
1244 using front = typename std::tuple_element<0, type_list>::type;
1246 if (arg.compare(front(0)) < 0)
1250 template <class Backend>
1251 inline BOOST_MP_CXX14_CONSTEXPR int eval_fpclassify(const Backend& arg)
1253 static_assert(number_category<Backend>::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types.");
1254 return eval_is_zero(arg) ? FP_ZERO : FP_NORMAL;
1258 inline BOOST_MP_CXX14_CONSTEXPR void eval_fmod(T& result, const T& a, const T& b)
1260 static_assert(number_category<T>::value == number_kind_floating_point, "The fmod function is only valid for floating point types.");
1261 if ((&result == &a) || (&result == &b))
1264 eval_fmod(temp, a, b);
1268 switch (eval_fpclassify(a))
1275 result = std::numeric_limits<number<T> >::quiet_NaN().backend();
1279 switch (eval_fpclassify(b))
1283 result = std::numeric_limits<number<T> >::quiet_NaN().backend();
1288 eval_divide(result, a, b);
1289 if (eval_get_sign(result) < 0)
1290 eval_ceil(n, result);
1292 eval_floor(n, result);
1293 eval_multiply(n, b);
1294 eval_subtract(result, a, n);
1296 template <class T, class A>
1297 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_fmod(T& result, const T& x, const A& a)
1299 using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1300 using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
1303 eval_fmod(result, x, c);
1306 template <class T, class A>
1307 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_fmod(T& result, const A& x, const T& a)
1309 using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1310 using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
1313 eval_fmod(result, c, a);
1317 BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a);
1320 inline BOOST_MP_CXX14_CONSTEXPR void eval_remquo(T& result, const T& a, const T& b, int* pi)
1322 static_assert(number_category<T>::value == number_kind_floating_point, "The remquo function is only valid for floating point types.");
1323 if ((&result == &a) || (&result == &b))
1326 eval_remquo(temp, a, b, pi);
1331 eval_divide(result, a, b);
1332 eval_round(n, result);
1333 eval_convert_to(pi, n);
1334 eval_multiply(n, b);
1335 eval_subtract(result, a, n);
1336 if (eval_is_zero(result))
1338 if (eval_signbit(a))
1342 template <class T, class A>
1343 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_remquo(T& result, const T& x, const A& a, int* pi)
1345 using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1346 using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
1347 cast_type c = cast_type();
1349 eval_remquo(result, x, c, pi);
1351 template <class T, class A>
1352 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_remquo(T& result, const A& x, const T& a, int* pi)
1354 using canonical_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1355 using cast_type = typename std::conditional<std::is_same<A, canonical_type>::value, T, canonical_type>::type;
1356 cast_type c = cast_type();
1358 eval_remquo(result, c, a, pi);
1360 template <class T, class U, class V>
1361 inline BOOST_MP_CXX14_CONSTEXPR void eval_remainder(T& result, const U& a, const V& b)
1364 eval_remquo(result, a, b, &i);
1368 BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const B& a, const B& b);
1369 template <class T, class U>
1370 BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const T& a, const U& b);
1372 BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const B& a, const B& b);
1373 template <class T, class U>
1374 BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const T& a, const U& b);
1377 inline BOOST_MP_CXX14_CONSTEXPR void eval_fdim(T& result, const T& a, const T& b)
1379 using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1380 const ui_type zero = 0u;
1381 switch (eval_fpclassify(b))
1388 switch (eval_fpclassify(a))
1399 eval_subtract(result, a, b);
1405 template <class T, class A>
1406 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value>::type eval_fdim(T& result, const T& a, const A& b)
1408 using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1409 using arithmetic_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1410 const ui_type zero = 0u;
1411 arithmetic_type canonical_b = b;
1412 switch (BOOST_MP_FPCLASSIFY(b))
1419 switch (eval_fpclassify(a))
1428 if (eval_gt(a, canonical_b))
1430 eval_subtract(result, a, canonical_b);
1436 template <class T, class A>
1437 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value>::type eval_fdim(T& result, const A& a, const T& b)
1439 using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1440 using arithmetic_type = typename boost::multiprecision::detail::canonical<A, T>::type ;
1441 const ui_type zero = 0u;
1442 arithmetic_type canonical_a = a;
1443 switch (eval_fpclassify(b))
1450 switch (BOOST_MP_FPCLASSIFY(a))
1456 result = std::numeric_limits<number<T> >::infinity().backend();
1459 if (eval_gt(canonical_a, b))
1461 eval_subtract(result, canonical_a, b);
1468 inline BOOST_MP_CXX14_CONSTEXPR void eval_trunc(T& result, const T& a)
1470 static_assert(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
1471 switch (eval_fpclassify(a))
1481 if (eval_get_sign(a) < 0)
1482 eval_ceil(result, a);
1484 eval_floor(result, a);
1488 inline BOOST_MP_CXX14_CONSTEXPR void eval_modf(T& result, T const& arg, T* pipart)
1490 using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1491 int c = eval_fpclassify(arg);
1492 if (c == static_cast<int>(FP_NAN))
1499 else if (c == static_cast<int>(FP_INFINITE))
1503 result = ui_type(0u);
1508 eval_trunc(*pipart, arg);
1509 eval_subtract(result, arg, *pipart);
1514 eval_trunc(ipart, arg);
1515 eval_subtract(result, arg, ipart);
1520 inline BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a)
1522 static_assert(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
1523 using fp_type = typename boost::multiprecision::detail::canonical<float, T>::type;
1524 int c = eval_fpclassify(a);
1525 if (c == static_cast<int>(FP_NAN))
1531 if ((c == FP_ZERO) || (c == static_cast<int>(FP_INFINITE)))
1535 else if (eval_get_sign(a) < 0)
1537 eval_subtract(result, a, fp_type(0.5f));
1538 eval_ceil(result, result);
1542 eval_add(result, a, fp_type(0.5f));
1543 eval_floor(result, result);
1548 BOOST_MP_CXX14_CONSTEXPR void eval_lcm(B& result, const B& a, const B& b);
1550 BOOST_MP_CXX14_CONSTEXPR void eval_gcd(B& result, const B& a, const B& b);
1552 template <class T, class Arithmetic>
1553 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_gcd(T& result, const T& a, const Arithmetic& b)
1555 using si_type = typename boost::multiprecision::detail::canonical<Arithmetic, T>::type;
1556 using default_ops::eval_gcd;
1558 t = static_cast<si_type>(b);
1559 eval_gcd(result, a, t);
1561 template <class T, class Arithmetic>
1562 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_gcd(T& result, const Arithmetic& a, const T& b)
1564 eval_gcd(result, b, a);
1566 template <class T, class Arithmetic>
1567 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_lcm(T& result, const T& a, const Arithmetic& b)
1569 using si_type = typename boost::multiprecision::detail::canonical<Arithmetic, T>::type;
1570 using default_ops::eval_lcm;
1572 t = static_cast<si_type>(b);
1573 eval_lcm(result, a, t);
1575 template <class T, class Arithmetic>
1576 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<Arithmetic>::value >::type eval_lcm(T& result, const Arithmetic& a, const T& b)
1578 eval_lcm(result, b, a);
1582 inline BOOST_MP_CXX14_CONSTEXPR std::size_t eval_lsb(const T& val)
1584 using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1585 int c = eval_get_sign(val);
1588 BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
1592 BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
1594 std::size_t result = 0;
1599 eval_bitwise_and(t, mask, val);
1601 eval_left_shift(mask, 1);
1602 } while (eval_is_zero(t));
1608 inline BOOST_MP_CXX14_CONSTEXPR std::ptrdiff_t eval_msb(const T& val)
1610 int c = eval_get_sign(val);
1613 BOOST_MP_THROW_EXCEPTION(std::domain_error("No bits were set in the operand."));
1617 BOOST_MP_THROW_EXCEPTION(std::domain_error("Testing individual bits in negative values is not supported - results are undefined."));
1620 // This implementation is really really rubbish - it does
1621 // a linear scan for the most-significant-bit. We should really
1622 // do a binary search, but as none of our backends actually needs
1623 // this implementation, we'll leave it for now. In fact for most
1624 // backends it's likely that there will always be a more efficient
1625 // native implementation possible.
1627 std::size_t result = 0;
1629 while (!eval_is_zero(t))
1631 eval_right_shift(t, 1);
1638 inline BOOST_MP_CXX14_CONSTEXPR bool eval_bit_test(const T& val, std::size_t index)
1640 using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1643 eval_left_shift(mask, index);
1644 eval_bitwise_and(t, mask, val);
1645 return !eval_is_zero(t);
1649 inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_set(T& val, std::size_t index)
1651 using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1654 eval_left_shift(mask, index);
1655 eval_bitwise_or(val, mask);
1659 inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_flip(T& val, std::size_t index)
1661 using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1664 eval_left_shift(mask, index);
1665 eval_bitwise_xor(val, mask);
1669 inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_unset(T& val, std::size_t index)
1671 using ui_type = typename boost::multiprecision::detail::canonical<unsigned, T>::type;
1674 eval_left_shift(mask, index);
1675 eval_bitwise_and(t, mask, val);
1676 if (!eval_is_zero(t))
1677 eval_bitwise_xor(val, mask);
1680 template <class Backend>
1681 BOOST_MP_CXX14_CONSTEXPR void eval_qr(const Backend& x, const Backend& y, Backend& q, Backend& r);
1683 template <class Backend>
1684 BOOST_MP_CXX14_CONSTEXPR void eval_karatsuba_sqrt(Backend& result, const Backend& x, Backend& r, Backend& t, size_t bits)
1686 using default_ops::eval_is_zero;
1687 using default_ops::eval_subtract;
1688 using default_ops::eval_right_shift;
1689 using default_ops::eval_left_shift;
1690 using default_ops::eval_bit_set;
1691 using default_ops::eval_decrement;
1692 using default_ops::eval_bitwise_and;
1693 using default_ops::eval_add;
1694 using default_ops::eval_qr;
1696 using small_uint = typename std::tuple_element<0, typename Backend::unsigned_types>::type;
1698 constexpr small_uint zero = 0u;
1700 // we can calculate it faster with std::sqrt
1701 #ifdef BOOST_HAS_INT128
1704 uint128_type a{}, b{}, c{};
1705 eval_convert_to(&a, x);
1706 c = boost::multiprecision::detail::karatsuba_sqrt(a, b, bits);
1707 r = number<Backend>::canonical_value(b);
1708 result = number<Backend>::canonical_value(c);
1712 if (bits <= std::numeric_limits<std::uintmax_t>::digits)
1714 std::uintmax_t a{ 0 }, b{ 0 }, c{ 0 };
1715 eval_convert_to(&a, x);
1716 c = boost::multiprecision::detail::karatsuba_sqrt(a, b, bits);
1717 r = number<Backend>::canonical_value(b);
1718 result = number<Backend>::canonical_value(c);
1722 // https://hal.inria.fr/file/index/docid/72854/filename/RR-3805.pdf
1723 std::size_t b = bits / 4;
1725 eval_right_shift(q, b * 2);
1727 eval_karatsuba_sqrt(s, q, r, t, bits - b * 2);
1729 eval_bit_set(t, static_cast<unsigned>(b * 2));
1730 eval_left_shift(r, b);
1732 eval_bitwise_and(t, x);
1733 eval_right_shift(t, b);
1735 eval_left_shift(s, 1u);
1736 eval_qr(t, s, q, r);
1737 eval_left_shift(r, b);
1739 eval_bit_set(t, static_cast<unsigned>(b));
1741 eval_bitwise_and(t, x);
1743 eval_left_shift(s, b - 1);
1745 eval_multiply(q, q);
1746 // we substract after, so it works for unsigned integers too
1747 if (r.compare(q) < 0)
1750 eval_left_shift(t, 1u);
1755 eval_subtract(r, q);
1760 void BOOST_MP_CXX14_CONSTEXPR eval_integer_sqrt_bitwise(B& s, B& r, const B& x)
1763 // This is slow bit-by-bit integer square root, see for example
1764 // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
1765 // There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf
1766 // and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented
1769 using ui_type = typename boost::multiprecision::detail::canonical<unsigned char, B>::type;
1772 if (eval_get_sign(x) == 0)
1777 std::ptrdiff_t g = eval_msb(x);
1781 eval_subtract(r, x, s);
1788 std::ptrdiff_t org_g = g;
1790 eval_bit_set(t, 2 * g);
1791 eval_subtract(r, x, t);
1793 if (eval_get_sign(r) == 0)
1795 std::ptrdiff_t msbr = eval_msb(r);
1798 if (msbr >= org_g + g + 1)
1801 eval_left_shift(t, g + 1);
1802 eval_bit_set(t, 2 * g);
1803 if (t.compare(r) <= 0)
1805 BOOST_MP_ASSERT(g >= 0);
1807 eval_subtract(r, t);
1808 if (eval_get_sign(r) == 0)
1817 template <class Backend>
1818 BOOST_MP_CXX14_CONSTEXPR void eval_integer_sqrt(Backend& result, Backend& r, const Backend& x)
1820 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
1821 // recursive Karatsuba sqrt can cause issues in constexpr context:
1822 if (BOOST_MP_IS_CONST_EVALUATED(result.size()))
1823 return eval_integer_sqrt_bitwise(result, r, x);
1825 using small_uint = typename std::tuple_element<0, typename Backend::unsigned_types>::type;
1827 constexpr small_uint zero = 0u;
1829 if (eval_is_zero(x))
1836 eval_karatsuba_sqrt(result, x, r, t, eval_msb(x) + 1);
1840 inline BOOST_MP_CXX14_CONSTEXPR void eval_conj(B& result, const B& val)
1842 result = val; // assume non-complex result.
1845 inline BOOST_MP_CXX14_CONSTEXPR void eval_proj(B& result, const B& val)
1847 result = val; // assume non-complex result.
1851 // These have to implemented by the backend, declared here so that our macro generated code compiles OK.
1854 typename std::enable_if<sizeof(T) == 0>::type eval_floor();
1856 typename std::enable_if<sizeof(T) == 0>::type eval_ceil();
1858 typename std::enable_if<sizeof(T) == 0>::type eval_trunc();
1860 typename std::enable_if<sizeof(T) == 0>::type eval_sqrt();
1862 typename std::enable_if<sizeof(T) == 0>::type eval_ldexp();
1864 typename std::enable_if<sizeof(T) == 0>::type eval_frexp();
1865 // TODO implement default versions of these:
1867 typename std::enable_if<sizeof(T) == 0>::type eval_asinh();
1869 typename std::enable_if<sizeof(T) == 0>::type eval_acosh();
1871 typename std::enable_if<sizeof(T) == 0>::type eval_atanh();
1874 // eval_logb and eval_scalbn simply assume base 2 and forward to
1875 // eval_ldexp and eval_frexp:
1878 inline BOOST_MP_CXX14_CONSTEXPR typename B::exponent_type eval_ilogb(const B& val)
1880 static_assert(!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");
1881 typename B::exponent_type e(0);
1882 switch (eval_fpclassify(val))
1886 return FP_ILOGBNAN > 0 ? (std::numeric_limits<typename B::exponent_type>::max)() : (std::numeric_limits<typename B::exponent_type>::min)();
1888 return (std::numeric_limits<typename B::exponent_type>::max)();
1891 return (std::numeric_limits<typename B::exponent_type>::max)();
1893 return (std::numeric_limits<typename B::exponent_type>::min)();
1896 eval_frexp(result, val, &e);
1901 inline BOOST_MP_CXX14_CONSTEXPR void eval_logb(B& result, const B& val)
1903 switch (eval_fpclassify(val))
1910 result = std::numeric_limits<number<B> >::infinity().backend();
1916 if (eval_signbit(val))
1920 using max_t = typename std::conditional<std::is_same<std::intmax_t, long>::value, long long, std::intmax_t>::type;
1921 result = static_cast<max_t>(eval_ilogb(val));
1923 template <class B, class A>
1924 inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbn(B& result, const B& val, A e)
1926 static_assert(!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");
1927 eval_ldexp(result, val, static_cast<typename B::exponent_type>(e));
1929 template <class B, class A>
1930 inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbln(B& result, const B& val, A e)
1932 eval_scalbn(result, val, e);
1936 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, std::integral_constant<bool, true> const&, const std::integral_constant<bool, false>&)
1938 return eval_fpclassify(val) == FP_NAN;
1941 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, std::integral_constant<bool, false> const&, const std::integral_constant<bool, true>&)
1943 return BOOST_MP_ISNAN(val);
1946 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T&, std::integral_constant<bool, false> const&, const std::integral_constant<bool, false>&)
1952 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val)
1954 return is_arg_nan(val, std::integral_constant<bool, boost::multiprecision::detail::is_backend<T>::value>(), std::is_floating_point<T>());
1957 template <class T, class U, class V>
1958 inline BOOST_MP_CXX14_CONSTEXPR void eval_fmax(T& result, const U& a, const V& b)
1961 result = number<T>::canonical_value(b);
1962 else if (is_arg_nan(b))
1963 result = number<T>::canonical_value(a);
1964 else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
1965 result = number<T>::canonical_value(b);
1967 result = number<T>::canonical_value(a);
1969 template <class T, class U, class V>
1970 inline BOOST_MP_CXX14_CONSTEXPR void eval_fmin(T& result, const U& a, const V& b)
1973 result = number<T>::canonical_value(b);
1974 else if (is_arg_nan(b))
1975 result = number<T>::canonical_value(a);
1976 else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
1977 result = number<T>::canonical_value(a);
1979 result = number<T>::canonical_value(b);
1982 template <class R, class T, class U>
1983 inline BOOST_MP_CXX14_CONSTEXPR void eval_hypot(R& result, const T& a, const U& b)
1986 // Normalize x and y, so that both are positive and x >= y:
1989 x = number<R>::canonical_value(a);
1990 y = number<R>::canonical_value(b);
1991 if (eval_get_sign(x) < 0)
1993 if (eval_get_sign(y) < 0)
1996 // Special case, see C99 Annex F.
1997 // The order of the if's is important: do not change!
1998 int c1 = eval_fpclassify(x);
1999 int c2 = eval_fpclassify(y);
2011 if (c1 == FP_INFINITE)
2016 if ((c2 == FP_INFINITE) || (c2 == FP_NAN))
2030 eval_multiply(result, x, std::numeric_limits<number<R> >::epsilon().backend());
2032 if (eval_gt(result, y))
2039 eval_divide(rat, y, x);
2040 eval_multiply(result, rat, rat);
2041 eval_increment(result);
2042 eval_sqrt(rat, result);
2043 eval_multiply(result, rat, x);
2046 template <class R, class T>
2047 inline BOOST_MP_CXX14_CONSTEXPR void eval_nearbyint(R& result, const T& a)
2049 eval_round(result, a);
2051 template <class R, class T>
2052 inline BOOST_MP_CXX14_CONSTEXPR void eval_rint(R& result, const T& a)
2054 eval_nearbyint(result, a);
2058 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_backend<T>::value, int>::type eval_signbit(const T& val)
2060 return eval_get_sign(val) < 0 ? 1 : 0;
2064 // Real and imaginary parts:
2066 template <class To, class From>
2067 inline BOOST_MP_CXX14_CONSTEXPR void eval_real(To& to, const From& from)
2071 template <class To, class From>
2072 inline BOOST_MP_CXX14_CONSTEXPR void eval_imag(To& to, const From&)
2074 using ui_type = typename std::tuple_element<0, typename To::unsigned_types>::type;
2078 } // namespace default_ops
2079 namespace default_ops_adl {
2081 template <class To, class From>
2082 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real_imp(To& to, const From& from)
2084 using to_component_type = typename component_type<number<To> >::type;
2085 typename to_component_type::backend_type to_component;
2086 to_component = from;
2087 eval_set_real(to, to_component);
2089 template <class To, class From>
2090 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag_imp(To& to, const From& from)
2092 using to_component_type = typename component_type<number<To> >::type;
2093 typename to_component_type::backend_type to_component;
2094 to_component = from;
2095 eval_set_imag(to, to_component);
2098 } // namespace default_ops_adl
2099 namespace default_ops {
2101 template <class To, class From>
2102 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<To>::value == number_kind_complex>::type eval_set_real(To& to, const From& from)
2104 default_ops_adl::eval_set_real_imp(to, from);
2106 template <class To, class From>
2107 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<To>::value != number_kind_complex>::type eval_set_real(To& to, const From& from)
2112 template <class To, class From>
2113 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(To& to, const From& from)
2115 default_ops_adl::eval_set_imag_imp(to, from);
2119 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(T& to, const T& from)
2124 void BOOST_MP_CXX14_CONSTEXPR eval_set_imag(T&, const T&)
2126 static_assert(sizeof(T) == INT_MAX, "eval_set_imag needs to be specialised for each specific backend");
2130 // These functions are implemented in separate files, but expanded inline here,
2131 // DO NOT CHANGE THE ORDER OF THESE INCLUDES:
2133 #include <boost/multiprecision/detail/functions/constants.hpp>
2134 #include <boost/multiprecision/detail/functions/pow.hpp>
2135 #include <boost/multiprecision/detail/functions/trig.hpp>
2137 } // namespace default_ops
2140 // Default versions of floating point classification routines:
2142 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2143 inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2145 using multiprecision::default_ops::eval_fpclassify;
2146 return eval_fpclassify(arg.backend());
2148 template <class tag, class A1, class A2, class A3, class A4>
2149 inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2151 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2152 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2154 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2155 inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2157 int v = fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg);
2158 return (v != static_cast<int>(FP_INFINITE)) && (v != static_cast<int>(FP_NAN));
2160 template <class tag, class A1, class A2, class A3, class A4>
2161 inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2163 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2164 return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2166 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2167 inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2169 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_NAN);
2171 template <class tag, class A1, class A2, class A3, class A4>
2172 inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2174 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2175 return isnan BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2177 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2178 inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2180 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_INFINITE);
2182 template <class tag, class A1, class A2, class A3, class A4>
2183 inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2185 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2186 return isinf BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2188 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2189 inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2191 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == static_cast<int>(FP_NORMAL);
2193 template <class tag, class A1, class A2, class A3, class A4>
2194 inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2196 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2197 return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2200 // Default versions of sign manipulation functions, if individual backends can do better than this
2201 // (for example with signed zero), then they should overload these functions further:
2203 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2204 inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2208 template <class tag, class A1, class A2, class A3, class A4>
2209 inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2211 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2212 return sign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2215 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2216 inline BOOST_MP_CXX14_CONSTEXPR bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2218 using default_ops::eval_signbit;
2219 return static_cast<bool>(eval_signbit(arg.backend()));
2221 template <class tag, class A1, class A2, class A3, class A4>
2222 inline BOOST_MP_CXX14_CONSTEXPR bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2224 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2225 return static_cast<bool>(signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)));
2227 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2228 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2232 template <class tag, class A1, class A2, class A3, class A4>
2233 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)
2235 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2236 return changesign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
2238 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2239 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)
2241 return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? (boost::multiprecision::changesign)(a) : a;
2243 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2244 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)
2246 return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
2248 template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
2249 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)
2251 return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
2253 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2254 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)
2256 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2257 return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
2262 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2263 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
2264 real(const multiprecision::number<Backend, ExpressionTemplates>& a)
2266 using default_ops::eval_real;
2267 using result_type = typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type;
2268 boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
2270 eval_real(result.backend(), a.backend());
2273 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2274 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
2275 imag(const multiprecision::number<Backend, ExpressionTemplates>& a)
2277 using default_ops::eval_imag;
2278 using result_type = typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type;
2279 boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
2281 eval_imag(result.backend(), a.backend());
2285 template <class tag, class A1, class A2, class A3, class A4>
2286 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2287 real(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2289 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2290 detail::scoped_default_precision<value_type> precision_guard(arg);
2291 return real(value_type(arg));
2294 template <class tag, class A1, class A2, class A3, class A4>
2295 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2296 imag(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2298 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2299 detail::scoped_default_precision<value_type> precision_guard(arg);
2300 return imag(value_type(arg));
2304 // Complex number functions, these are overloaded at the Backend level, we just provide the
2305 // expression template versions here, plus overloads for non-complex types:
2307 #ifdef BOOST_MP_MATH_AVAILABLE
2308 template <class T, expression_template_option ExpressionTemplates>
2309 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates>>>::type::type
2310 abs(const number<T, ExpressionTemplates>& v)
2312 return std::move(boost::math::hypot(real(v), imag(v)));
2314 template <class tag, class A1, class A2, class A3, class A4>
2315 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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::type
2316 abs(const detail::expression<tag, A1, A2, A3, A4>& v)
2318 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2319 return std::move(abs(static_cast<number_type>(v)));
2322 template <class T, expression_template_option ExpressionTemplates>
2323 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
2324 arg(const number<T, ExpressionTemplates>& v)
2326 return std::move(atan2(imag(v), real(v)));
2328 template <class T, expression_template_option ExpressionTemplates>
2329 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
2330 arg(const number<T, ExpressionTemplates>&)
2334 template <class tag, class A1, class A2, class A3, class A4>
2335 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
2336 arg(const detail::expression<tag, A1, A2, A3, A4>& v)
2338 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2339 return std::move(arg(static_cast<number_type>(v)));
2341 #endif // BOOST_MP_MATH_AVAILABLE
2343 template <class T, expression_template_option ExpressionTemplates>
2344 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates>>>::type::type
2345 norm(const number<T, ExpressionTemplates>& v)
2347 typename component_type<number<T, ExpressionTemplates> >::type a(real(v)), b(imag(v));
2348 return std::move(a * a + b * b);
2350 template <class T, expression_template_option ExpressionTemplates>
2351 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value != number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
2352 norm(const number<T, ExpressionTemplates>& v)
2356 template <class tag, class A1, class A2, class A3, class A4>
2357 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2358 norm(const detail::expression<tag, A1, A2, A3, A4>& v)
2360 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2361 return std::move(norm(static_cast<number_type>(v)));
2364 template <class Backend, expression_template_option ExpressionTemplates>
2365 BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r, number<Backend, ExpressionTemplates> const& theta)
2367 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2370 template <class tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
2371 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
2372 typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
2373 polar(detail::expression<tag, A1, A2, A3, A4> const& r, number<Backend, ExpressionTemplates> const& theta)
2375 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2378 template <class Backend, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2379 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
2380 typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
2381 polar(number<Backend, ExpressionTemplates> const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
2383 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2386 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2387 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<std::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, typename detail::expression<tagb, A1b, A2b, A3b, A4b>::result_type>::value,
2388 typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
2389 polar(detail::expression<tag, A1, A2, A3, A4> const& r, detail::expression<tagb, A1b, A2b, A3b, A4b> const& theta)
2391 using scalar_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2392 return typename complex_result_from_scalar<scalar_type>::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta)));
2395 // We also allow the first argument to polar to be an arithmetic type (probably a literal):
2397 template <class Scalar, class Backend, expression_template_option ExpressionTemplates>
2398 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<Scalar>::value, typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
2399 polar(Scalar const& r, number<Backend, ExpressionTemplates> const& theta)
2401 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2404 template <class tag, class A1, class A2, class A3, class A4, class Scalar>
2405 BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<Scalar>::value,
2406 typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
2407 polar(Scalar const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
2409 using scalar_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2410 return typename complex_result_from_scalar<scalar_type>::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta)));
2413 // Single argument overloads:
2415 template <class Backend, expression_template_option ExpressionTemplates>
2416 BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r)
2418 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(r);
2421 template <class tag, class A1, class A2, class A3, class A4>
2422 BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2423 polar(detail::expression<tag, A1, A2, A3, A4> const& r)
2425 return typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type(r);
2428 } // namespace multiprecision
2433 // Import Math functions here, so they can be found by Boost.Math:
2435 using boost::multiprecision::changesign;
2436 using boost::multiprecision::copysign;
2437 using boost::multiprecision::fpclassify;
2438 using boost::multiprecision::isfinite;
2439 using boost::multiprecision::isinf;
2440 using boost::multiprecision::isnan;
2441 using boost::multiprecision::isnormal;
2442 using boost::multiprecision::sign;
2443 using boost::multiprecision::signbit;
2445 #ifndef BOOST_MP_MATH_AVAILABLE
2446 namespace policies {
2448 template <typename... Args>
2451 template <typename T1, typename T2, typename T3, typename T4, typename T5>
2452 void raise_rounding_error(T1, T2, T3, T4, T5)
2454 BOOST_MP_THROW_EXCEPTION(std::runtime_error("Rounding error"));
2457 template <typename T1, typename T2, typename T3, typename T4, typename T5>
2458 void raise_overflow_error(T1, T2, T3, T4, T5)
2460 BOOST_MP_THROW_EXCEPTION(std::runtime_error("Overflow error"));
2463 template <typename T1, typename T2, typename T3, typename T4, typename T5>
2464 void raise_evaluation_error(T1, T2, T3, T4, T5)
2466 BOOST_MP_THROW_EXCEPTION(std::runtime_error("Evaluation error"));
2469 template <typename T, typename... Args>
2472 static constexpr bool value = false;
2475 template <typename... Args>
2476 struct is_policy<policy<Args...>>
2478 static constexpr bool value = true;
2481 } // namespace policies
2486 namespace multiprecision {
2487 #ifdef BOOST_MP_MATH_AVAILABLE
2488 using c99_error_policy = ::boost::math::policies::policy<
2489 ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>,
2490 ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>,
2491 ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>,
2492 ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>,
2493 ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error> >;
2495 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2496 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2498 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2500 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2501 return boost::math::asinh(arg, c99_error_policy());
2503 template <class tag, class A1, class A2, class A3, class A4>
2504 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
2506 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2508 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2509 detail::scoped_default_precision<value_type> precision_guard(arg);
2510 return asinh(value_type(arg));
2512 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2513 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2515 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2517 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2518 return boost::math::acosh(arg, c99_error_policy());
2520 template <class tag, class A1, class A2, class A3, class A4>
2521 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
2523 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2525 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2526 detail::scoped_default_precision<value_type> precision_guard(arg);
2527 return acosh(value_type(arg));
2529 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2530 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2532 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2534 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2535 return boost::math::atanh(arg, c99_error_policy());
2537 template <class tag, class A1, class A2, class A3, class A4>
2538 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
2540 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2542 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2543 detail::scoped_default_precision<value_type> precision_guard(arg);
2544 return atanh(value_type(arg));
2546 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2547 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2549 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2550 return boost::math::cbrt(arg, c99_error_policy());
2552 template <class tag, class A1, class A2, class A3, class A4>
2553 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)
2555 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2556 detail::scoped_default_precision<value_type> precision_guard(arg);
2557 return cbrt(value_type(arg));
2559 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2560 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2562 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2563 return boost::math::erf(arg, c99_error_policy());
2565 template <class tag, class A1, class A2, class A3, class A4>
2566 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)
2568 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2569 detail::scoped_default_precision<value_type> precision_guard(arg);
2570 return erf(value_type(arg));
2572 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2573 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2575 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2576 return boost::math::erfc(arg, c99_error_policy());
2578 template <class tag, class A1, class A2, class A3, class A4>
2579 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)
2581 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2582 detail::scoped_default_precision<value_type> precision_guard(arg);
2583 return erfc(value_type(arg));
2585 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2586 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2588 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2589 return boost::math::expm1(arg, c99_error_policy());
2591 template <class tag, class A1, class A2, class A3, class A4>
2592 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)
2594 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2595 detail::scoped_default_precision<value_type> precision_guard(arg);
2596 return expm1(value_type(arg));
2598 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2599 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2601 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2602 multiprecision::number<Backend, ExpressionTemplates> result;
2603 result = boost::math::lgamma(arg, c99_error_policy());
2604 if ((boost::multiprecision::isnan)(result) && !(boost::multiprecision::isnan)(arg))
2606 result = std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::infinity();
2611 template <class tag, class A1, class A2, class A3, class A4>
2612 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)
2614 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2615 detail::scoped_default_precision<value_type> precision_guard(arg);
2616 return lgamma(value_type(arg));
2618 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2619 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2621 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2622 if ((arg == 0) && std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::has_infinity)
2627 return boost::math::tgamma(arg, c99_error_policy());
2629 template <class tag, class A1, class A2, class A3, class A4>
2630 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)
2632 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2633 detail::scoped_default_precision<value_type> precision_guard(arg);
2634 return tgamma(value_type(arg));
2637 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2638 inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2642 template <class tag, class A1, class A2, class A3, class A4>
2643 inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2647 #ifndef BOOST_NO_LONG_LONG
2648 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2649 inline BOOST_MP_CXX14_CONSTEXPR long long llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2651 return llround(arg);
2653 template <class tag, class A1, class A2, class A3, class A4>
2654 inline BOOST_MP_CXX14_CONSTEXPR long long llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2656 return llround(arg);
2659 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2660 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2662 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2663 return boost::math::log1p(arg, c99_error_policy());
2665 template <class tag, class A1, class A2, class A3, class A4>
2666 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)
2668 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2669 detail::scoped_default_precision<value_type> precision_guard(arg);
2670 return log1p(value_type(arg));
2673 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2674 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)
2676 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2677 return boost::math::nextafter(a, b, c99_error_policy());
2679 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2680 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)
2682 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2683 return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
2685 template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
2686 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)
2688 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2689 return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
2691 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2692 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)
2694 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2695 detail::scoped_default_precision<value_type> precision_guard(a, b);
2696 return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
2698 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2699 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)
2701 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2702 return boost::math::nextafter(a, b, c99_error_policy());
2704 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2705 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)
2707 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2708 return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
2710 template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
2711 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)
2713 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2714 return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
2716 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2717 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)
2719 using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
2720 detail::scoped_default_precision<value_type> precision_guard(a, b);
2721 return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
2723 #endif // BOOST_MP_MATH_AVAILABLE
2725 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
2726 inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2728 static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2729 static_assert((std::is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2730 using default_ops::eval_add;
2731 eval_add(result.backend(), a.backend(), b.backend());
2735 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
2736 inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2738 static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2739 static_assert((std::is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2740 using default_ops::eval_subtract;
2741 eval_subtract(result.backend(), a.backend(), b.backend());
2745 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
2746 inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2748 static_assert((std::is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2749 static_assert((std::is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2750 using default_ops::eval_multiply;
2751 eval_multiply(result.backend(), a.backend(), b.backend());
2755 template <class B, expression_template_option ET, class I>
2756 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
2757 add(number<B, ET>& result, const I& a, const I& b)
2759 using default_ops::eval_add;
2760 using canonical_type = typename detail::canonical<I, B>::type;
2761 eval_add(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2765 template <class B, expression_template_option ET, class I>
2766 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
2767 subtract(number<B, ET>& result, const I& a, const I& b)
2769 using default_ops::eval_subtract;
2770 using canonical_type = typename detail::canonical<I, B>::type;
2771 eval_subtract(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2775 template <class B, expression_template_option ET, class I>
2776 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value, number<B, ET>&>::type
2777 multiply(number<B, ET>& result, const I& a, const I& b)
2779 using default_ops::eval_multiply;
2780 using canonical_type = typename detail::canonical<I, B>::type;
2781 eval_multiply(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2785 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2786 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)
2788 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2789 return std::move(trunc(number_type(v), pol));
2792 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
2793 inline BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates> trunc(const number<Backend, ExpressionTemplates>& v, const Policy&)
2795 using default_ops::eval_trunc;
2796 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(v);
2797 number<Backend, ExpressionTemplates> result;
2798 eval_trunc(result.backend(), v.backend());
2802 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2803 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2805 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2806 number_type r(trunc(v, pol));
2807 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
2808 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, number_type(v), 0, pol);
2809 return r.template convert_to<int>();
2811 template <class tag, class A1, class A2, class A3, class A4>
2812 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2814 return itrunc(v, boost::math::policies::policy<>());
2816 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
2817 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v, const Policy& pol)
2819 number<Backend, ExpressionTemplates> r(trunc(v, pol));
2820 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
2821 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol);
2822 return r.template convert_to<int>();
2824 template <class Backend, expression_template_option ExpressionTemplates>
2825 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v)
2827 return itrunc(v, boost::math::policies::policy<>());
2829 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2830 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2832 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2833 number_type r(trunc(v, pol));
2834 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
2835 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, number_type(v), 0L, pol);
2836 return r.template convert_to<long>();
2838 template <class tag, class A1, class A2, class A3, class A4>
2839 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2841 return ltrunc(v, boost::math::policies::policy<>());
2843 template <class T, expression_template_option ExpressionTemplates, class Policy>
2844 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
2846 number<T, ExpressionTemplates> r(trunc(v, pol));
2847 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
2848 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol);
2849 return r.template convert_to<long>();
2851 template <class T, expression_template_option ExpressionTemplates>
2852 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v)
2854 return ltrunc(v, boost::math::policies::policy<>());
2856 #ifndef BOOST_NO_LONG_LONG
2857 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2858 inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2860 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2861 number_type r(trunc(v, pol));
2862 if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
2863 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, pol);
2864 return r.template convert_to<long long>();
2866 template <class tag, class A1, class A2, class A3, class A4>
2867 inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2869 return lltrunc(v, boost::math::policies::policy<>());
2871 template <class T, expression_template_option ExpressionTemplates, class Policy>
2872 inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
2874 number<T, ExpressionTemplates> r(trunc(v, pol));
2875 if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
2876 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol);
2877 return r.template convert_to<long long>();
2879 template <class T, expression_template_option ExpressionTemplates>
2880 inline BOOST_MP_CXX14_CONSTEXPR long long lltrunc(const number<T, ExpressionTemplates>& v)
2882 return lltrunc(v, boost::math::policies::policy<>());
2885 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2886 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)
2888 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2889 return std::move(round(static_cast<number_type>(v), pol));
2891 template <class T, expression_template_option ExpressionTemplates, class Policy>
2892 inline BOOST_MP_CXX14_CONSTEXPR number<T, ExpressionTemplates> round(const number<T, ExpressionTemplates>& v, const Policy&)
2894 using default_ops::eval_round;
2895 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2896 number<T, ExpressionTemplates> result;
2897 eval_round(result.backend(), v.backend());
2901 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2902 inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2904 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2905 number_type r(round(v, pol));
2906 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
2907 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0, pol);
2908 return r.template convert_to<int>();
2910 template <class tag, class A1, class A2, class A3, class A4>
2911 inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v)
2913 return iround(v, boost::math::policies::policy<>());
2915 template <class T, expression_template_option ExpressionTemplates, class Policy>
2916 inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v, const Policy& pol)
2918 number<T, ExpressionTemplates> r(round(v, pol));
2919 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !BOOST_MP_ISFINITE(v))
2920 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol);
2921 return r.template convert_to<int>();
2923 template <class T, expression_template_option ExpressionTemplates>
2924 inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v)
2926 return iround(v, boost::math::policies::policy<>());
2928 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2929 inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2931 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2932 number_type r(round(v, pol));
2933 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
2934 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, number_type(v), 0L, pol);
2935 return r.template convert_to<long>();
2937 template <class tag, class A1, class A2, class A3, class A4>
2938 inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v)
2940 return lround(v, boost::math::policies::policy<>());
2942 template <class T, expression_template_option ExpressionTemplates, class Policy>
2943 inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v, const Policy& pol)
2945 number<T, ExpressionTemplates> r(round(v, pol));
2946 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !BOOST_MP_ISFINITE(v))
2947 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol);
2948 return r.template convert_to<long>();
2950 template <class T, expression_template_option ExpressionTemplates>
2951 inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v)
2953 return lround(v, boost::math::policies::policy<>());
2955 #ifndef BOOST_NO_LONG_LONG
2956 template <class tag, class A1, class A2, class A3, class A4, class Policy>
2957 inline BOOST_MP_CXX14_CONSTEXPR long long llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2959 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
2960 number_type r(round(v, pol));
2961 if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
2962 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol);
2963 return r.template convert_to<long long>();
2965 template <class tag, class A1, class A2, class A3, class A4>
2966 inline BOOST_MP_CXX14_CONSTEXPR long long llround(const detail::expression<tag, A1, A2, A3, A4>& v)
2968 return llround(v, boost::math::policies::policy<>());
2970 template <class T, expression_template_option ExpressionTemplates, class Policy>
2971 inline BOOST_MP_CXX14_CONSTEXPR long long llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
2973 number<T, ExpressionTemplates> r(round(v, pol));
2974 if ((r > (std::numeric_limits<long long>::max)()) || r < (std::numeric_limits<long long>::min)() || !BOOST_MP_ISFINITE(v))
2975 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol);
2976 return r.template convert_to<long long>();
2978 template <class T, expression_template_option ExpressionTemplates>
2979 inline BOOST_MP_CXX14_CONSTEXPR long long llround(const number<T, ExpressionTemplates>& v)
2981 return llround(v, boost::math::policies::policy<>());
2985 // frexp does not return an expression template since we require the
2986 // integer argument to be evaluated even if the returned value is
2987 // not assigned to anything...
2989 template <class T, expression_template_option ExpressionTemplates>
2990 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, short* pint)
2992 using default_ops::eval_frexp;
2993 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2994 number<T, ExpressionTemplates> result;
2995 eval_frexp(result.backend(), v.backend(), pint);
2998 template <class tag, class A1, class A2, class A3, class A4>
2999 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
3000 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, short* pint)
3002 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
3003 return std::move(frexp(static_cast<number_type>(v), pint));
3005 template <class T, expression_template_option ExpressionTemplates>
3006 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, int* pint)
3008 using default_ops::eval_frexp;
3009 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
3010 number<T, ExpressionTemplates> result;
3011 eval_frexp(result.backend(), v.backend(), pint);
3014 template <class tag, class A1, class A2, class A3, class A4>
3015 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
3016 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, int* pint)
3018 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
3019 return std::move(frexp(static_cast<number_type>(v), pint));
3021 template <class T, expression_template_option ExpressionTemplates>
3022 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long* pint)
3024 using default_ops::eval_frexp;
3025 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
3026 number<T, ExpressionTemplates> result;
3027 eval_frexp(result.backend(), v.backend(), pint);
3030 template <class tag, class A1, class A2, class A3, class A4>
3031 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
3032 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long* pint)
3034 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
3035 return std::move(frexp(static_cast<number_type>(v), pint));
3037 template <class T, expression_template_option ExpressionTemplates>
3038 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long long* pint)
3040 using default_ops::eval_frexp;
3041 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
3042 number<T, ExpressionTemplates> result;
3043 eval_frexp(result.backend(), v.backend(), pint);
3046 template <class tag, class A1, class A2, class A3, class A4>
3047 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
3048 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long long* pint)
3050 using number_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
3051 return std::move(frexp(static_cast<number_type>(v), pint));
3054 // modf does not return an expression template since we require the
3055 // second argument to be evaluated even if the returned value is
3056 // not assigned to anything...
3058 template <class T, expression_template_option ExpressionTemplates>
3059 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const number<T, ExpressionTemplates>& v, number<T, ExpressionTemplates>* pipart)
3061 using default_ops::eval_modf;
3062 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
3063 number<T, ExpressionTemplates> result;
3064 eval_modf(result.backend(), v.backend(), pipart ? &pipart->backend() : 0);
3067 template <class T, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
3068 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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)
3070 using default_ops::eval_modf;
3071 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
3072 number<T, ExpressionTemplates> result, arg(v);
3073 eval_modf(result.backend(), arg.backend(), pipart ? &pipart->backend() : 0);
3078 // Integer square root:
3080 template <class B, expression_template_option ExpressionTemplates>
3081 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
3082 sqrt(const number<B, ExpressionTemplates>& x)
3084 using default_ops::eval_integer_sqrt;
3085 number<B, ExpressionTemplates> s, r;
3086 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
3089 template <class tag, class A1, class A2, class A3, class A4>
3090 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_integer, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
3091 sqrt(const detail::expression<tag, A1, A2, A3, A4>& arg)
3093 using default_ops::eval_integer_sqrt;
3094 using result_type = typename detail::expression<tag, A1, A2, A3, A4>::result_type;
3095 detail::scoped_default_precision<result_type> precision_guard(arg);
3096 result_type result, v(arg), r;
3097 eval_integer_sqrt(result.backend(), r.backend(), v.backend());
3105 namespace default_ops {
3109 template <class B, class T, class U, class V>
3110 BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, const V& c) const
3112 eval_multiply_add(result, a, b, c);
3116 } // namespace default_ops
3118 template <class Backend, class U, class V>
3119 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3120 (number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
3121 (is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
3122 (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3123 detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V> >::type
3124 fma(const number<Backend, et_on>& a, const U& b, const V& c)
3126 return detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V>(
3127 default_ops::fma_func(), a, b, c);
3130 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U, class V>
3131 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3132 (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
3133 (is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
3134 (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3135 detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V> >::type
3136 fma(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, const V& c)
3138 return detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V>(
3139 default_ops::fma_func(), a, b, c);
3142 template <class Backend, class U, class V>
3143 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3144 (number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
3145 (is_number<U>::value || is_number_expression<U>::value || boost::multiprecision::detail::is_arithmetic<U>::value) &&
3146 (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3147 number<Backend, et_off> >::type
3148 fma(const number<Backend, et_off>& a, const U& b, const V& c)
3150 using default_ops::eval_multiply_add;
3151 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
3152 number<Backend, et_off> result;
3153 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));
3157 template <class U, class Backend, class V>
3158 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3159 (number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
3160 boost::multiprecision::detail::is_arithmetic<U>::value &&
3161 (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3162 detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V> >::type
3163 fma(const U& a, const number<Backend, et_on>& b, const V& c)
3165 return detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V>(
3166 default_ops::fma_func(), a, b, c);
3169 template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
3170 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3171 (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
3172 boost::multiprecision::detail::is_arithmetic<U>::value &&
3173 (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3174 detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
3175 fma(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, const V& c)
3177 return detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(
3178 default_ops::fma_func(), a, b, c);
3181 template <class U, class Backend, class V>
3182 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3183 (number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
3184 boost::multiprecision::detail::is_arithmetic<U>::value &&
3185 (is_number<V>::value || is_number_expression<V>::value || boost::multiprecision::detail::is_arithmetic<V>::value),
3186 number<Backend, et_off> >::type
3187 fma(const U& a, const number<Backend, et_off>& b, const V& c)
3189 using default_ops::eval_multiply_add;
3190 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
3191 number<Backend, et_off> result;
3192 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));
3196 template <class U, class V, class Backend>
3197 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3198 (number_category<number<Backend, et_on> >::value == number_kind_floating_point) &&
3199 boost::multiprecision::detail::is_arithmetic<U>::value &&
3200 boost::multiprecision::detail::is_arithmetic<V>::value,
3201 detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> > >::type
3202 fma(const U& a, const V& b, const number<Backend, et_on>& c)
3204 return detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> >(
3205 default_ops::fma_func(), a, b, c);
3208 template <class U, class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
3209 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3210 (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) &&
3211 boost::multiprecision::detail::is_arithmetic<U>::value &&
3212 boost::multiprecision::detail::is_arithmetic<V>::value,
3213 detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
3214 fma(const U& a, const V& b, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& c)
3216 return detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(
3217 default_ops::fma_func(), a, b, c);
3220 template <class U, class V, class Backend>
3221 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3222 (number_category<number<Backend, et_off> >::value == number_kind_floating_point) &&
3223 boost::multiprecision::detail::is_arithmetic<U>::value &&
3224 boost::multiprecision::detail::is_arithmetic<V>::value,
3225 number<Backend, et_off> >::type
3226 fma(const U& a, const V& b, const number<Backend, et_off>& c)
3228 using default_ops::eval_multiply_add;
3229 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
3230 number<Backend, et_off> result;
3231 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));
3235 namespace default_ops {
3239 template <class B, class T, class U>
3240 BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, int* pi) const
3242 eval_remquo(result, a, b, pi);
3246 } // namespace default_ops
3248 template <class Backend, class U>
3249 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3250 number_category<number<Backend, et_on> >::value == number_kind_floating_point,
3251 detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*> >::type
3252 remquo(const number<Backend, et_on>& a, const U& b, int* pi)
3254 return detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*>(
3255 default_ops::remquo_func(), a, b, pi);
3258 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U>
3259 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3260 number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point,
3261 detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*> >::type
3262 remquo(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, int* pi)
3264 return detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*>(
3265 default_ops::remquo_func(), a, b, pi);
3268 template <class U, class Backend>
3269 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3270 (number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
3271 detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*> >::type
3272 remquo(const U& a, const number<Backend, et_on>& b, int* pi)
3274 return detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*>(
3275 default_ops::remquo_func(), a, b, pi);
3278 template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
3279 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3280 (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,
3281 detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*> >::type
3282 remquo(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, int* pi)
3284 return detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*>(
3285 default_ops::remquo_func(), a, b, pi);
3288 template <class Backend, class U>
3289 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3290 number_category<number<Backend, et_on> >::value == number_kind_floating_point,
3291 number<Backend, et_off> >::type
3292 remquo(const number<Backend, et_off>& a, const U& b, int* pi)
3294 using default_ops::eval_remquo;
3295 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
3296 number<Backend, et_off> result;
3297 eval_remquo(result.backend(), a.backend(), number<Backend, et_off>::canonical_value(b), pi);
3300 template <class U, class Backend>
3301 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
3302 (number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
3303 number<Backend, et_off> >::type
3304 remquo(const U& a, const number<Backend, et_off>& b, int* pi)
3306 using default_ops::eval_remquo;
3307 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
3308 number<Backend, et_off> result;
3309 eval_remquo(result.backend(), number<Backend, et_off>::canonical_value(a), b.backend(), pi);
3313 template <class B, expression_template_option ExpressionTemplates>
3314 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
3315 sqrt(const number<B, ExpressionTemplates>& x, number<B, ExpressionTemplates>& r)
3317 using default_ops::eval_integer_sqrt;
3318 detail::scoped_default_precision<multiprecision::number<B, ExpressionTemplates> > precision_guard(x, r);
3319 number<B, ExpressionTemplates> s;
3320 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
3323 template <class B, expression_template_option ExpressionTemplates, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
3324 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
3325 sqrt(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& arg, number<B, ExpressionTemplates>& r)
3327 using default_ops::eval_integer_sqrt;
3328 detail::scoped_default_precision<multiprecision::number<B, ExpressionTemplates> > precision_guard(r);
3329 number<B, ExpressionTemplates> s;
3330 number<B, ExpressionTemplates> x(arg);
3331 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
3337 // Regrettably, when the argument to a function is an rvalue we must return by value, and not return an
3338 // expression template, otherwise we can end up with dangling references.
3339 // See https://github.com/boostorg/multiprecision/issues/175.
3341 #define UNARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
3342 template <class Backend> \
3343 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> > ::type \
3344 func(number<Backend, et_on>&& arg) \
3346 detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg); \
3347 number<Backend, et_on> result; \
3348 using default_ops::BOOST_JOIN(eval_, func); \
3349 BOOST_JOIN(eval_, func)(result.backend(), arg.backend()); \
3353 #define BINARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
3354 template <class Backend> \
3355 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(number<Backend, et_on>&& arg, const number<Backend, et_on>& a) \
3357 detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
3358 number<Backend, et_on> result; \
3359 using default_ops::BOOST_JOIN(eval_, func); \
3360 BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3363 template <class Backend> \
3364 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(const number<Backend, et_on>& arg, number<Backend, et_on>&& a) \
3366 detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
3367 number<Backend, et_on> result; \
3368 using default_ops::BOOST_JOIN(eval_, func); \
3369 BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3372 template <class Backend> \
3373 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, number<Backend, et_on> >::type func(number<Backend, et_on>&& arg, number<Backend, et_on>&& a) \
3375 detail::scoped_default_precision<multiprecision::number<Backend, et_on> > precision_guard(arg, a); \
3376 number<Backend, et_on> result; \
3377 using default_ops::BOOST_JOIN(eval_, func); \
3378 BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3381 template <class Backend, class tag, class A1, class A2, class A3, class A4> \
3382 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3383 number<Backend, et_on> > ::type \
3384 func(number<Backend, et_on>&& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
3386 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3387 number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3389 template <class tag, class A1, class A2, class A3, class A4, class Backend> \
3390 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3391 number<Backend, et_on> > ::type \
3392 func(const detail::expression<tag, A1, A2, A3, A4>& arg, number<Backend, et_on>&& a) \
3394 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3395 detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3397 template <class Backend, class Arithmetic> \
3398 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3399 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3400 number<Backend, et_on> >::type \
3401 func(number<Backend, et_on>&& arg, const Arithmetic& a) \
3403 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, \
3404 number<Backend, et_on>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3406 template <class Backend, class Arithmetic> \
3407 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3408 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3409 number<Backend, et_on> > ::type \
3410 func(const Arithmetic& arg, number<Backend, et_on>&& a) \
3412 return detail::expression< \
3413 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3414 Arithmetic, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3418 #define UNARY_OP_FUNCTOR(func, category) \
3419 namespace detail { \
3420 template <class Backend> \
3421 struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3423 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const \
3425 using default_ops::BOOST_JOIN(eval_, func); \
3426 BOOST_JOIN(eval_, func) \
3429 template <class U> \
3430 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg) const \
3432 using default_ops::BOOST_JOIN(eval_, func); \
3434 BOOST_JOIN(eval_, func) \
3436 result = std::move(temp); \
3441 template <class tag, class A1, class A2, class A3, class A4> \
3442 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category, \
3443 detail::expression<detail::function, \
3444 detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3445 detail::expression<tag, A1, A2, A3, A4> > > ::type \
3446 func(const detail::expression<tag, A1, A2, A3, A4>& arg) \
3448 return detail::expression< \
3449 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3450 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); \
3452 template <class Backend> \
3453 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, \
3454 detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, number<Backend, et_on> > > ::type \
3455 func(const number<Backend, et_on>& arg) \
3457 return detail::expression< \
3458 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3459 number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg); \
3461 template <class Backend> \
3462 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3463 boost::multiprecision::number_category<Backend>::value == category, \
3464 number<Backend, et_off> >::type \
3465 func(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::BOOST_JOIN(eval_, func); \
3470 BOOST_JOIN(eval_, func)(result.backend(), arg.backend()); \
3473 UNARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
3475 #define BINARY_OP_FUNCTOR(func, category) \
3476 namespace detail { \
3477 template <class Backend> \
3478 struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3480 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg, const Backend& a) const \
3482 using default_ops::BOOST_JOIN(eval_, func); \
3483 BOOST_JOIN(eval_, func) \
3486 template <class Arithmetic> \
3487 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg, const Arithmetic& a) const \
3489 using default_ops::BOOST_JOIN(eval_, func); \
3490 BOOST_JOIN(eval_, func) \
3491 (result, arg, number<Backend>::canonical_value(a)); \
3493 template <class Arithmetic> \
3494 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Arithmetic& arg, const Backend& a) const \
3496 using default_ops::BOOST_JOIN(eval_, func); \
3497 BOOST_JOIN(eval_, func) \
3498 (result, number<Backend>::canonical_value(arg), a); \
3500 template <class U> \
3501 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg, const Backend& a) const \
3503 using default_ops::BOOST_JOIN(eval_, func); \
3505 BOOST_JOIN(eval_, func) \
3507 result = std::move(r); \
3509 template <class U, class Arithmetic> \
3510 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg, const Arithmetic& a) const \
3512 using default_ops::BOOST_JOIN(eval_, func); \
3514 BOOST_JOIN(eval_, func) \
3515 (r, arg, number<Backend>::canonical_value(a)); \
3516 result = std::move(r); \
3518 template <class U, class Arithmetic> \
3519 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Arithmetic& arg, const Backend& a) const \
3521 using default_ops::BOOST_JOIN(eval_, func); \
3523 BOOST_JOIN(eval_, func) \
3524 (r, number<Backend>::canonical_value(arg), a); \
3525 result = std::move(r); \
3529 template <class Backend> \
3530 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == category, detail::expression<detail::function, \
3531 detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, number<Backend, et_on>, number<Backend, et_on> > > ::type \
3532 func(const number<Backend, et_on>& arg, const number<Backend, et_on>& a) \
3534 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3535 number<Backend, et_on>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3537 template <class Backend, class tag, class A1, class A2, class A3, class A4> \
3538 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3539 detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > > ::type \
3540 func(const number<Backend, et_on>& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
3542 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3543 number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3545 template <class tag, class A1, class A2, class A3, class A4, class Backend> \
3546 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category) && (std::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3547 detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > > ::type \
3548 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const number<Backend, et_on>& a) \
3550 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3551 detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3553 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> \
3554 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category) && (number_category<detail::expression<tagb, A1b, A2b, A3b, A4b> >::value == category), \
3555 detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3556 detail::expression<tag, A1, A2, A3, A4>, detail::expression<tagb, A1b, A2b, A3b, A4b> > > ::type \
3557 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const detail::expression<tagb, A1b, A2b, A3b, A4b>& a) \
3559 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3560 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); \
3562 template <class Backend, class Arithmetic> \
3563 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3564 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3565 detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3566 number<Backend, et_on>, Arithmetic> > ::type \
3567 func(const number<Backend, et_on>& arg, const Arithmetic& a) \
3569 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, \
3570 number<Backend, et_on>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3572 template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
3573 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3574 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), \
3575 detail::expression< \
3576 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3577 detail::expression<tag, A1, A2, A3, A4>, Arithmetic> > ::type \
3578 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const Arithmetic& a) \
3580 return detail::expression< \
3581 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3582 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); \
3584 template <class Backend, class Arithmetic> \
3585 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3586 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3587 detail::expression< \
3588 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3589 Arithmetic, number<Backend, et_on> > > ::type \
3590 func(const Arithmetic& arg, const number<Backend, et_on>& a) \
3592 return detail::expression< \
3593 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3594 Arithmetic, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3596 template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
3597 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3598 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), \
3599 detail::expression< \
3600 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3601 Arithmetic, detail::expression<tag, A1, A2, A3, A4> > > ::type \
3602 func(const Arithmetic& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
3604 return detail::expression< \
3605 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3606 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); \
3608 template <class Backend> \
3609 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value == category), number<Backend, et_off> >::type \
3610 func(const number<Backend, et_off>& arg, const number<Backend, et_off>& a) \
3612 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
3613 number<Backend, et_off> result; \
3614 using default_ops::BOOST_JOIN(eval_, func); \
3615 BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3618 template <class Backend, class Arithmetic> \
3619 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3620 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
3621 number<Backend, et_off> >::type \
3622 func(const number<Backend, et_off>& arg, const Arithmetic& a) \
3624 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3625 number<Backend, et_off> result; \
3626 using default_ops::BOOST_JOIN(eval_, func); \
3627 BOOST_JOIN(eval_, func) \
3628 (result.backend(), arg.backend(), number<Backend, et_off>::canonical_value(a)); \
3631 template <class Backend, class Arithmetic> \
3632 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3633 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
3634 number<Backend, et_off> >::type \
3635 func(const Arithmetic& a, const number<Backend, et_off>& arg) \
3637 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3638 number<Backend, et_off> result; \
3639 using default_ops::BOOST_JOIN(eval_, func); \
3640 BOOST_JOIN(eval_, func) \
3641 (result.backend(), number<Backend, et_off>::canonical_value(a), arg.backend()); \
3644 BINARY_OP_FUNCTOR_CXX11_RVALUE(func, category)
3646 #define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category) \
3647 template <class tag, class A1, class A2, class A3, class A4> \
3648 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3649 (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
3650 detail::expression< \
3651 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3652 detail::expression<tag, A1, A2, A3, A4>, Arg2> > ::type \
3653 func(const detail::expression<tag, A1, A2, A3, A4>& arg, Arg2 const& a) \
3655 return detail::expression< \
3656 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3657 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); \
3659 template <class Backend> \
3660 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3661 (number_category<Backend>::value == category), \
3662 detail::expression< \
3663 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3664 number<Backend, et_on>, Arg2> > ::type \
3665 func(const number<Backend, et_on>& arg, Arg2 const& a) \
3667 return detail::expression< \
3668 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3669 number<Backend, et_on>, Arg2 > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3671 template <class Backend> \
3672 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if< \
3673 (number_category<Backend>::value == category), \
3674 number<Backend, et_off> >::type \
3675 func(const number<Backend, et_off>& arg, Arg2 const& a) \
3677 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
3678 number<Backend, et_off> result; \
3679 using default_ops::BOOST_JOIN(eval_, func); \
3680 BOOST_JOIN(eval_, func) \
3681 (result.backend(), arg.backend(), a); \
3685 #define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category) \
3686 namespace detail { \
3687 template <class Backend> \
3688 struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3690 template <class Arg> \
3691 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, Backend const& arg, Arg a) const \
3693 using default_ops::BOOST_JOIN(eval_, func); \
3694 BOOST_JOIN(eval_, func) \
3697 template <class U, class Arg> \
3698 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, Backend const& arg, Arg a) const \
3700 using default_ops::BOOST_JOIN(eval_, func); \
3702 BOOST_JOIN(eval_, func) \
3704 result = std::move(temp); \
3709 HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)
3714 template <class Backend>
3717 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3719 using default_ops::eval_abs;
3720 eval_abs(result, arg);
3723 template <class Backend>
3726 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3728 using default_ops::eval_conj;
3729 eval_conj(result, arg);
3732 template <class Backend>
3735 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3737 using default_ops::eval_proj;
3738 eval_proj(result, arg);
3742 } // namespace detail
3744 template <class tag, class A1, class A2, class A3, class A4>
3745 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex,
3747 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
3748 abs(const detail::expression<tag, A1, A2, A3, A4>& arg)
3750 return detail::expression<
3751 detail::function, detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3752 detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3754 template <class Backend>
3755 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex,
3757 detail::function, detail::abs_funct<Backend>, number<Backend, et_on> > >::type
3758 abs(const number<Backend, et_on>& arg)
3760 return detail::expression<
3761 detail::function, detail::abs_funct<Backend>, number<Backend, et_on> >(
3762 detail::abs_funct<Backend>(), arg);
3764 template <class Backend>
3765 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value != number_kind_complex, number<Backend, et_off> >::type
3766 abs(const number<Backend, et_off>& arg)
3768 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3769 number<Backend, et_off> result;
3770 using default_ops::eval_abs;
3771 eval_abs(result.backend(), arg.backend());
3775 template <class tag, class A1, class A2, class A3, class A4>
3776 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3777 detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
3778 conj(const detail::expression<tag, A1, A2, A3, A4>& arg)
3780 return detail::expression<
3781 detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3782 detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3784 template <class Backend>
3785 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3786 detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >
3787 conj(const number<Backend, et_on>& arg)
3789 return detail::expression<
3790 detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >(
3791 detail::conj_funct<Backend>(), arg);
3793 template <class Backend>
3794 inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
3795 conj(const number<Backend, et_off>& arg)
3797 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3798 number<Backend, et_off> result;
3799 using default_ops::eval_conj;
3800 eval_conj(result.backend(), arg.backend());
3804 template <class tag, class A1, class A2, class A3, class A4>
3805 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3806 detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
3807 proj(const detail::expression<tag, A1, A2, A3, A4>& arg)
3809 return detail::expression<
3810 detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3811 detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3813 template <class Backend>
3814 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3815 detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >
3816 proj(const number<Backend, et_on>& arg)
3818 return detail::expression<
3819 detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >(
3820 detail::proj_funct<Backend>(), arg);
3822 template <class Backend>
3823 inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
3824 proj(const number<Backend, et_off>& arg)
3826 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3827 number<Backend, et_off> result;
3828 using default_ops::eval_proj;
3829 eval_proj(result.backend(), arg.backend());
3833 UNARY_OP_FUNCTOR(fabs, number_kind_floating_point)
3834 UNARY_OP_FUNCTOR(sqrt, number_kind_floating_point)
3835 UNARY_OP_FUNCTOR(floor, number_kind_floating_point)
3836 UNARY_OP_FUNCTOR(ceil, number_kind_floating_point)
3837 UNARY_OP_FUNCTOR(trunc, number_kind_floating_point)
3838 UNARY_OP_FUNCTOR(round, number_kind_floating_point)
3839 UNARY_OP_FUNCTOR(exp, number_kind_floating_point)
3840 UNARY_OP_FUNCTOR(exp2, number_kind_floating_point)
3841 UNARY_OP_FUNCTOR(log, number_kind_floating_point)
3842 UNARY_OP_FUNCTOR(log10, number_kind_floating_point)
3843 UNARY_OP_FUNCTOR(cos, number_kind_floating_point)
3844 UNARY_OP_FUNCTOR(sin, number_kind_floating_point)
3845 UNARY_OP_FUNCTOR(tan, number_kind_floating_point)
3846 UNARY_OP_FUNCTOR(asin, number_kind_floating_point)
3847 UNARY_OP_FUNCTOR(acos, number_kind_floating_point)
3848 UNARY_OP_FUNCTOR(atan, number_kind_floating_point)
3849 UNARY_OP_FUNCTOR(cosh, number_kind_floating_point)
3850 UNARY_OP_FUNCTOR(sinh, number_kind_floating_point)
3851 UNARY_OP_FUNCTOR(tanh, number_kind_floating_point)
3852 UNARY_OP_FUNCTOR(log2, number_kind_floating_point)
3853 UNARY_OP_FUNCTOR(nearbyint, number_kind_floating_point)
3854 UNARY_OP_FUNCTOR(rint, number_kind_floating_point)
3856 HETERO_BINARY_OP_FUNCTOR(ldexp, short, number_kind_floating_point)
3857 //HETERO_BINARY_OP_FUNCTOR(frexp, short*, number_kind_floating_point)
3858 HETERO_BINARY_OP_FUNCTOR_B(ldexp, int, number_kind_floating_point)
3859 //HETERO_BINARY_OP_FUNCTOR_B(frexp, int*, number_kind_floating_point)
3860 HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point)
3861 //HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point)
3862 HETERO_BINARY_OP_FUNCTOR_B(ldexp, long long, number_kind_floating_point)
3863 //HETERO_BINARY_OP_FUNCTOR_B(frexp, long long*, number_kind_floating_point)
3864 BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
3865 BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
3866 BINARY_OP_FUNCTOR(fmax, number_kind_floating_point)
3867 BINARY_OP_FUNCTOR(fmin, number_kind_floating_point)
3868 BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
3869 BINARY_OP_FUNCTOR(fdim, number_kind_floating_point)
3870 BINARY_OP_FUNCTOR(hypot, number_kind_floating_point)
3871 BINARY_OP_FUNCTOR(remainder, number_kind_floating_point)
3873 UNARY_OP_FUNCTOR(logb, number_kind_floating_point)
3874 HETERO_BINARY_OP_FUNCTOR(scalbn, short, number_kind_floating_point)
3875 HETERO_BINARY_OP_FUNCTOR(scalbln, short, number_kind_floating_point)
3876 HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point)
3877 HETERO_BINARY_OP_FUNCTOR_B(scalbln, int, number_kind_floating_point)
3878 HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point)
3879 HETERO_BINARY_OP_FUNCTOR_B(scalbln, long, number_kind_floating_point)
3880 HETERO_BINARY_OP_FUNCTOR_B(scalbn, long long, number_kind_floating_point)
3881 HETERO_BINARY_OP_FUNCTOR_B(scalbln, long long, number_kind_floating_point)
3884 // Complex functions:
3886 UNARY_OP_FUNCTOR(exp, number_kind_complex)
3887 UNARY_OP_FUNCTOR(log, number_kind_complex)
3888 UNARY_OP_FUNCTOR(log10, number_kind_complex)
3889 BINARY_OP_FUNCTOR(pow, number_kind_complex)
3890 UNARY_OP_FUNCTOR(sqrt, number_kind_complex)
3891 UNARY_OP_FUNCTOR(sin, number_kind_complex)
3892 UNARY_OP_FUNCTOR(cos, number_kind_complex)
3893 UNARY_OP_FUNCTOR(tan, number_kind_complex)
3894 UNARY_OP_FUNCTOR(asin, number_kind_complex)
3895 UNARY_OP_FUNCTOR(acos, number_kind_complex)
3896 UNARY_OP_FUNCTOR(atan, number_kind_complex)
3897 UNARY_OP_FUNCTOR(sinh, number_kind_complex)
3898 UNARY_OP_FUNCTOR(cosh, number_kind_complex)
3899 UNARY_OP_FUNCTOR(tanh, number_kind_complex)
3900 UNARY_OP_FUNCTOR(asinh, number_kind_complex)
3901 UNARY_OP_FUNCTOR(acosh, number_kind_complex)
3902 UNARY_OP_FUNCTOR(atanh, number_kind_complex)
3905 // Integer functions:
3907 BINARY_OP_FUNCTOR(gcd, number_kind_integer)
3908 BINARY_OP_FUNCTOR(lcm, number_kind_integer)
3909 HETERO_BINARY_OP_FUNCTOR(pow, unsigned, number_kind_integer)
3911 #undef BINARY_OP_FUNCTOR
3912 #undef UNARY_OP_FUNCTOR
3917 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
3918 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<Backend>::value == number_kind_floating_point, typename Backend::exponent_type>::type
3919 ilogb(const multiprecision::number<Backend, ExpressionTemplates>& val)
3921 using default_ops::eval_ilogb;
3922 return eval_ilogb(val.backend());
3925 template <class tag, class A1, class A2, class A3, class A4>
3926 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
3927 ilogb(const detail::expression<tag, A1, A2, A3, A4>& val)
3929 using default_ops::eval_ilogb;
3930 typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type arg(val);
3931 return eval_ilogb(arg.backend());
3934 } //namespace multiprecision
3938 // Overload of Boost.Math functions that find the wrong overload when used with number:
3945 } // namespace detail
3946 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
3947 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
3949 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3950 return std::move(detail::sinc_pi_imp(x));
3953 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
3954 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
3956 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3957 return std::move(detail::sinc_pi_imp(x));
3960 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
3961 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
3963 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3964 return std::move(detail::sinhc_pi_imp(x));
3967 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
3968 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
3970 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3971 return std::move(boost::math::sinhc_pi(x));
3974 using boost::multiprecision::gcd;
3975 using boost::multiprecision::lcm;
3978 #pragma warning(pop)
3984 using boost::multiprecision::gcd;
3985 using boost::multiprecision::lcm;
3987 } // namespace integer
3989 } // namespace boost
3992 // This has to come last of all:
3994 #include <boost/multiprecision/detail/no_et_ops.hpp>
3995 #include <boost/multiprecision/detail/et_ops.hpp>
3997 // min/max overloads:
3999 #include <boost/multiprecision/detail/min_max.hpp>