1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright 2011 John Maddock. Distributed under the Boost
3 // Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #ifndef BOOST_MATH_BIG_NUM_DEF_OPS
7 #define BOOST_MATH_BIG_NUM_DEF_OPS
8
9 #include <boost/math/policies/error_handling.hpp>
10 #include <boost/multiprecision/detail/number_base.hpp>
11 #include <boost/math/special_functions/fpclassify.hpp>
12 #include <boost/math/special_functions/next.hpp>
13 #include <boost/math/special_functions/hypot.hpp>
14 #include <boost/utility/enable_if.hpp>
15 #include <boost/mpl/front.hpp>
16 #include <boost/mpl/fold.hpp>
17 #include <boost/cstdint.hpp>
18 #include <boost/type_traits/make_unsigned.hpp>
19 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
20 #include <string_view>
21 #endif
22
23 #ifndef INSTRUMENT_BACKEND
24 #ifndef BOOST_MP_INSTRUMENT
25 #define INSTRUMENT_BACKEND(x)
26 #else
27 #define INSTRUMENT_BACKEND(x) \
28 std::cout << BOOST_STRINGIZE(x) << " = " << x.str(0, std::ios_base::scientific) << std::endl;
29 #endif
30 #endif
31
32 namespace boost {
33 namespace multiprecision {
34
35 namespace detail {
36
37 template <class T>
38 struct is_backend;
39
40 template <class To, class From>
41 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
42 template <class To, class From>
43 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
44 template <class To, class From>
45 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/);
46 template <class To, class From>
47 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/);
48 template <class To, class From>
49 void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
50
51 } // namespace detail
52
53 namespace default_ops {
54
55 #ifdef BOOST_MSVC
56 // warning C4127: conditional expression is constant
57 // warning C4146: unary minus operator applied to unsigned type, result still unsigned
58 #pragma warning(push)
59 #pragma warning(disable : 4127 4146)
60 #endif
61 //
62 // Default versions of mixed arithmetic, these just construct a temporary
63 // from the arithmetic value and then do the arithmetic on that, two versions
64 // of each depending on whether the backend can be directly constructed from type V.
65 //
66 // Note that we have to provide *all* the template parameters to class number when used in
67 // enable_if as MSVC-10 won't compile the code if we rely on a computed-default parameter.
68 // Since the result of the test doesn't depend on whether expression templates are on or off
69 // we just use et_on everywhere. We could use a BOOST_WORKAROUND but that just obfuscates the
70 // code even more....
71 //
72 template <class T, class V>
73 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<is_convertible<V, T>::value>::type
eval_add(T & result,V const & v)74 eval_add(T& result, V const& v)
75 {
76 T t;
77 t = v;
78 eval_add(result, t);
79 }
80 template <class T, class V>
81 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, T>::value>::type
eval_add(T & result,V const & v)82 eval_add(T& result, V const& v)
83 {
84 T t(v);
85 eval_add(result, t);
86 }
87 template <class T, class V>
88 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<is_convertible<V, T>::value>::type
eval_subtract(T & result,V const & v)89 eval_subtract(T& result, V const& v)
90 {
91 T t;
92 t = v;
93 eval_subtract(result, t);
94 }
95 template <class T, class V>
96 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, T>::value>::type
eval_subtract(T & result,V const & v)97 eval_subtract(T& result, V const& v)
98 {
99 T t(v);
100 eval_subtract(result, t);
101 }
102 template <class T, class V>
103 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<is_convertible<V, T>::value>::type
eval_multiply(T & result,V const & v)104 eval_multiply(T& result, V const& v)
105 {
106 T t;
107 t = v;
108 eval_multiply(result, t);
109 }
110 template <class T, class V>
111 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, T>::value>::type
eval_multiply(T & result,V const & v)112 eval_multiply(T& result, V const& v)
113 {
114 T t(v);
115 eval_multiply(result, t);
116 }
117
118 template <class T, class U, class V>
119 BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v);
120
121 template <class T, class U, class V>
eval_multiply_add(T & t,const U & u,const V & v)122 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
123 {
124 T z;
125 eval_multiply(z, u, v);
126 eval_add(t, z);
127 }
128 template <class T, class U, class V>
eval_multiply_add(T & t,const U & u,const V & v)129 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
130 {
131 eval_multiply_add(t, v, u);
132 }
133 template <class T, class U, class V>
eval_multiply_subtract(T & t,const U & u,const V & v)134 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
135 {
136 T z;
137 eval_multiply(z, u, v);
138 eval_subtract(t, z);
139 }
140 template <class T, class U, class V>
eval_multiply_subtract(T & t,const U & u,const V & v)141 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
142 {
143 eval_multiply_subtract(t, v, u);
144 }
145 template <class T, class V>
146 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
eval_divide(T & result,V const & v)147 eval_divide(T& result, V const& v)
148 {
149 T t;
150 t = v;
151 eval_divide(result, t);
152 }
153 template <class T, class V>
154 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
eval_divide(T & result,V const & v)155 eval_divide(T& result, V const& v)
156 {
157 T t(v);
158 eval_divide(result, t);
159 }
160 template <class T, class V>
161 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
eval_modulus(T & result,V const & v)162 eval_modulus(T& result, V const& v)
163 {
164 T t;
165 t = v;
166 eval_modulus(result, t);
167 }
168 template <class T, class V>
169 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
eval_modulus(T & result,V const & v)170 eval_modulus(T& result, V const& v)
171 {
172 T t(v);
173 eval_modulus(result, t);
174 }
175 template <class T, class V>
176 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
eval_bitwise_and(T & result,V const & v)177 eval_bitwise_and(T& result, V const& v)
178 {
179 T t;
180 t = v;
181 eval_bitwise_and(result, t);
182 }
183 template <class T, class V>
184 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
eval_bitwise_and(T & result,V const & v)185 eval_bitwise_and(T& result, V const& v)
186 {
187 T t(v);
188 eval_bitwise_and(result, t);
189 }
190 template <class T, class V>
191 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
eval_bitwise_or(T & result,V const & v)192 eval_bitwise_or(T& result, V const& v)
193 {
194 T t;
195 t = v;
196 eval_bitwise_or(result, t);
197 }
198 template <class T, class V>
199 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
eval_bitwise_or(T & result,V const & v)200 eval_bitwise_or(T& result, V const& v)
201 {
202 T t(v);
203 eval_bitwise_or(result, t);
204 }
205 template <class T, class V>
206 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
eval_bitwise_xor(T & result,V const & v)207 eval_bitwise_xor(T& result, V const& v)
208 {
209 T t;
210 t = v;
211 eval_bitwise_xor(result, t);
212 }
213 template <class T, class V>
214 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
eval_bitwise_xor(T & result,V const & v)215 eval_bitwise_xor(T& result, V const& v)
216 {
217 T t(v);
218 eval_bitwise_xor(result, t);
219 }
220
221 template <class T, class V>
222 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
eval_complement(T & result,V const & v)223 eval_complement(T& result, V const& v)
224 {
225 T t;
226 t = v;
227 eval_complement(result, t);
228 }
229 template <class T, class V>
230 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
eval_complement(T & result,V const & v)231 eval_complement(T& result, V const& v)
232 {
233 T t(v);
234 eval_complement(result, t);
235 }
236
237 //
238 // Default versions of 3-arg arithmetic functions, these mostly just forward to the 2 arg versions:
239 //
240 template <class T, class U, class V>
241 BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v);
242
243 template <class T>
eval_add_default(T & t,const T & u,const T & v)244 inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const T& u, const T& v)
245 {
246 if (&t == &v)
247 {
248 eval_add(t, u);
249 }
250 else if (&t == &u)
251 {
252 eval_add(t, v);
253 }
254 else
255 {
256 t = u;
257 eval_add(t, v);
258 }
259 }
260 template <class T, class U>
eval_add_default(T & t,const T & u,const U & v)261 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
262 {
263 T vv;
264 vv = v;
265 eval_add(t, u, vv);
266 }
267 template <class T, class U>
eval_add_default(T & t,const T & u,const U & v)268 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
269 {
270 T vv(v);
271 eval_add(t, u, vv);
272 }
273 template <class T, class U>
eval_add_default(T & t,const U & u,const T & v)274 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_add_default(T& t, const U& u, const T& v)
275 {
276 eval_add(t, v, u);
277 }
278 template <class T, class U, class V>
eval_add_default(T & t,const U & u,const V & v)279 inline BOOST_MP_CXX14_CONSTEXPR void eval_add_default(T& t, const U& u, const V& v)
280 {
281 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
282 {
283 eval_add(t, u);
284 }
285 else
286 {
287 t = u;
288 eval_add(t, v);
289 }
290 }
291 template <class T, class U, class V>
eval_add(T & t,const U & u,const V & v)292 inline BOOST_MP_CXX14_CONSTEXPR void eval_add(T& t, const U& u, const V& v)
293 {
294 eval_add_default(t, u, v);
295 }
296
297 template <class T, class U, class V>
298 void BOOST_MP_CXX14_CONSTEXPR eval_subtract(T& t, const U& u, const V& v);
299
300 template <class T>
eval_subtract_default(T & t,const T & u,const T & v)301 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const T& u, const T& v)
302 {
303 if ((&t == &v) && is_signed_number<T>::value)
304 {
305 eval_subtract(t, u);
306 t.negate();
307 }
308 else if (&t == &u)
309 {
310 eval_subtract(t, v);
311 }
312 else
313 {
314 t = u;
315 eval_subtract(t, v);
316 }
317 }
318 template <class T, class U>
eval_subtract_default(T & t,const T & u,const U & v)319 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
320 {
321 T vv;
322 vv = v;
323 eval_subtract(t, u, vv);
324 }
325 template <class T, class U>
eval_subtract_default(T & t,const T & u,const U & v)326 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
327 {
328 T vv(v);
329 eval_subtract(t, u, vv);
330 }
331 template <class T, class U>
eval_subtract_default(T & t,const U & u,const T & v)332 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
333 {
334 eval_subtract(t, v, u);
335 t.negate();
336 }
337 template <class T, class U>
eval_subtract_default(T & t,const U & u,const T & v)338 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
339 {
340 T temp;
341 temp = u;
342 eval_subtract(t, temp, v);
343 }
344 template <class T, class U>
eval_subtract_default(T & t,const U & u,const T & v)345 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
346 {
347 T temp(u);
348 eval_subtract(t, temp, v);
349 }
350 template <class T, class U, class V>
eval_subtract_default(T & t,const U & u,const V & v)351 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract_default(T& t, const U& u, const V& v)
352 {
353 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
354 {
355 eval_subtract(t, u);
356 t.negate();
357 }
358 else
359 {
360 t = u;
361 eval_subtract(t, v);
362 }
363 }
364 template <class T, class U, class V>
eval_subtract(T & t,const U & u,const V & v)365 inline BOOST_MP_CXX14_CONSTEXPR void eval_subtract(T& t, const U& u, const V& v)
366 {
367 eval_subtract_default(t, u, v);
368 }
369
370 template <class T>
eval_multiply_default(T & t,const T & u,const T & v)371 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const T& u, const T& v)
372 {
373 if (&t == &v)
374 {
375 eval_multiply(t, u);
376 }
377 else if (&t == &u)
378 {
379 eval_multiply(t, v);
380 }
381 else
382 {
383 t = u;
384 eval_multiply(t, v);
385 }
386 }
387 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
388 template <class T, class U>
eval_multiply_default(T & t,const T & u,const U & v)389 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
390 {
391 T vv;
392 vv = v;
393 eval_multiply(t, u, vv);
394 }
395 template <class T, class U>
eval_multiply_default(T & t,const T & u,const U & v)396 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
397 {
398 T vv(v);
399 eval_multiply(t, u, vv);
400 }
401 template <class T, class U>
eval_multiply_default(T & t,const U & u,const T & v)402 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_multiply_default(T& t, const U& u, const T& v)
403 {
404 eval_multiply(t, v, u);
405 }
406 #endif
407 template <class T, class U, class V>
eval_multiply_default(T & t,const U & u,const V & v)408 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_default(T& t, const U& u, const V& v)
409 {
410 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
411 {
412 eval_multiply(t, u);
413 }
414 else
415 {
416 t = number<T>::canonical_value(u);
417 eval_multiply(t, v);
418 }
419 }
420 template <class T, class U, class V>
eval_multiply(T & t,const U & u,const V & v)421 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply(T& t, const U& u, const V& v)
422 {
423 eval_multiply_default(t, u, v);
424 }
425
426 template <class T>
eval_multiply_add(T & t,const T & u,const T & v,const T & x)427 inline BOOST_MP_CXX14_CONSTEXPR void eval_multiply_add(T& t, const T& u, const T& v, const T& x)
428 {
429 if ((void*)&x == (void*)&t)
430 {
431 T z;
432 z = number<T>::canonical_value(x);
433 eval_multiply_add(t, u, v, z);
434 }
435 else
436 {
437 eval_multiply(t, u, v);
438 eval_add(t, x);
439 }
440 }
441
442 template <class T, class U>
make_T(const U & u)443 inline BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<boost::is_same<T, U>::value, T>::type make_T(const U& u)
444 {
445 T t;
446 t = number<T>::canonical_value(u);
447 return t;
448 }
449 template <class T>
make_T(const T & t)450 inline BOOST_MP_CXX14_CONSTEXPR const T& make_T(const T& t)
451 {
452 return t;
453 }
454
455 template <class T, class U, class V, class X>
eval_multiply_add(T & t,const U & u,const V & v,const X & x)456 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
457 {
458 eval_multiply_add(t, make_T<T>(u), make_T<T>(v), make_T<T>(x));
459 }
460 template <class T, class U, class V, class X>
eval_multiply_add(T & t,const U & u,const V & v,const X & x)461 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
462 {
463 eval_multiply_add(t, v, u, x);
464 }
465 template <class T, class U, class V, class X>
eval_multiply_subtract(T & t,const U & u,const V & v,const X & x)466 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
467 {
468 if ((void*)&x == (void*)&t)
469 {
470 T z;
471 z = x;
472 eval_multiply_subtract(t, u, v, z);
473 }
474 else
475 {
476 eval_multiply(t, u, v);
477 eval_subtract(t, x);
478 }
479 }
480 template <class T, class U, class V, class X>
eval_multiply_subtract(T & t,const U & u,const V & v,const X & x)481 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
482 {
483 eval_multiply_subtract(t, v, u, x);
484 }
485
486 template <class T, class U, class V>
487 BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v);
488
489 template <class T>
eval_divide_default(T & t,const T & u,const T & v)490 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const T& u, const T& v)
491 {
492 if (&t == &u)
493 eval_divide(t, v);
494 else if (&t == &v)
495 {
496 T temp;
497 eval_divide(temp, u, v);
498 temp.swap(t);
499 }
500 else
501 {
502 t = u;
503 eval_divide(t, v);
504 }
505 }
506 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
507 template <class T, class U>
eval_divide_default(T & t,const T & u,const U & v)508 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
509 {
510 T vv;
511 vv = v;
512 eval_divide(t, u, vv);
513 }
514 template <class T, class U>
eval_divide_default(T & t,const T & u,const U & v)515 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
516 {
517 T vv(v);
518 eval_divide(t, u, vv);
519 }
520 template <class T, class U>
eval_divide_default(T & t,const U & u,const T & v)521 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
522 {
523 T uu;
524 uu = u;
525 eval_divide(t, uu, v);
526 }
527 template <class T, class U>
eval_divide_default(T & t,const U & u,const T & v)528 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
529 {
530 T uu(u);
531 eval_divide(t, uu, v);
532 }
533 #endif
534 template <class T, class U, class V>
eval_divide_default(T & t,const U & u,const V & v)535 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide_default(T& t, const U& u, const V& v)
536 {
537 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
538 {
539 T temp;
540 temp = u;
541 eval_divide(temp, v);
542 t = temp;
543 }
544 else
545 {
546 t = u;
547 eval_divide(t, v);
548 }
549 }
550 template <class T, class U, class V>
eval_divide(T & t,const U & u,const V & v)551 inline BOOST_MP_CXX14_CONSTEXPR void eval_divide(T& t, const U& u, const V& v)
552 {
553 eval_divide_default(t, u, v);
554 }
555
556 template <class T, class U, class V>
557 BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v);
558
559 template <class T>
eval_modulus_default(T & t,const T & u,const T & v)560 inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const T& u, const T& v)
561 {
562 if (&t == &u)
563 eval_modulus(t, v);
564 else if (&t == &v)
565 {
566 T temp;
567 eval_modulus(temp, u, v);
568 temp.swap(t);
569 }
570 else
571 {
572 t = u;
573 eval_modulus(t, v);
574 }
575 }
576 template <class T, class U>
eval_modulus_default(T & t,const T & u,const U & v)577 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
578 {
579 T vv;
580 vv = v;
581 eval_modulus(t, u, vv);
582 }
583 template <class T, class U>
eval_modulus_default(T & t,const T & u,const U & v)584 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
585 {
586 T vv(v);
587 eval_modulus(t, u, vv);
588 }
589 template <class T, class U>
eval_modulus_default(T & t,const U & u,const T & v)590 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
591 {
592 T uu;
593 uu = u;
594 eval_modulus(t, uu, v);
595 }
596 template <class T, class U>
eval_modulus_default(T & t,const U & u,const T & v)597 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
598 {
599 T uu(u);
600 eval_modulus(t, uu, v);
601 }
602 template <class T, class U, class V>
eval_modulus_default(T & t,const U & u,const V & v)603 inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus_default(T& t, const U& u, const V& v)
604 {
605 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
606 {
607 T temp(u);
608 eval_modulus(temp, v);
609 t = temp;
610 }
611 else
612 {
613 t = u;
614 eval_modulus(t, v);
615 }
616 }
617 template <class T, class U, class V>
eval_modulus(T & t,const U & u,const V & v)618 inline BOOST_MP_CXX14_CONSTEXPR void eval_modulus(T& t, const U& u, const V& v)
619 {
620 eval_modulus_default(t, u, v);
621 }
622
623 template <class T, class U, class V>
624 BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v);
625
626 template <class T>
eval_bitwise_and_default(T & t,const T & u,const T & v)627 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and_default(T& t, const T& u, const T& v)
628 {
629 if (&t == &v)
630 {
631 eval_bitwise_and(t, u);
632 }
633 else if (&t == &u)
634 {
635 eval_bitwise_and(t, v);
636 }
637 else
638 {
639 t = u;
640 eval_bitwise_and(t, v);
641 }
642 }
643 template <class T, class U>
eval_bitwise_and_default(T & t,const T & u,const U & v)644 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
645 {
646 T vv;
647 vv = v;
648 eval_bitwise_and(t, u, vv);
649 }
650 template <class T, class U>
eval_bitwise_and_default(T & t,const T & u,const U & v)651 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
652 {
653 T vv(v);
654 eval_bitwise_and(t, u, vv);
655 }
656 template <class T, class U>
eval_bitwise_and_default(T & t,const U & u,const T & v)657 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v)
658 {
659 eval_bitwise_and(t, v, u);
660 }
661 template <class T, class U, class V>
eval_bitwise_and_default(T & t,const U & u,const V & v)662 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<is_same<T, U>::value || is_same<T, V>::value>::type eval_bitwise_and_default(T& t, const U& u, const V& v)
663 {
664 t = u;
665 eval_bitwise_and(t, v);
666 }
667 template <class T, class U, class V>
eval_bitwise_and(T & t,const U & u,const V & v)668 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_and(T& t, const U& u, const V& v)
669 {
670 eval_bitwise_and_default(t, u, v);
671 }
672
673 template <class T, class U, class V>
674 BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v);
675
676 template <class T>
eval_bitwise_or_default(T & t,const T & u,const T & v)677 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const T& u, const T& v)
678 {
679 if (&t == &v)
680 {
681 eval_bitwise_or(t, u);
682 }
683 else if (&t == &u)
684 {
685 eval_bitwise_or(t, v);
686 }
687 else
688 {
689 t = u;
690 eval_bitwise_or(t, v);
691 }
692 }
693 template <class T, class U>
eval_bitwise_or_default(T & t,const T & u,const U & v)694 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
695 {
696 T vv;
697 vv = v;
698 eval_bitwise_or(t, u, vv);
699 }
700 template <class T, class U>
eval_bitwise_or_default(T & t,const T & u,const U & v)701 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
702 {
703 T vv(v);
704 eval_bitwise_or(t, u, vv);
705 }
706 template <class T, class U>
eval_bitwise_or_default(T & t,const U & u,const T & v)707 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v)
708 {
709 eval_bitwise_or(t, v, u);
710 }
711 template <class T, class U, class V>
eval_bitwise_or_default(T & t,const U & u,const V & v)712 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or_default(T& t, const U& u, const V& v)
713 {
714 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
715 {
716 eval_bitwise_or(t, u);
717 }
718 else
719 {
720 t = u;
721 eval_bitwise_or(t, v);
722 }
723 }
724 template <class T, class U, class V>
eval_bitwise_or(T & t,const U & u,const V & v)725 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_or(T& t, const U& u, const V& v)
726 {
727 eval_bitwise_or_default(t, u, v);
728 }
729
730 template <class T, class U, class V>
731 BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v);
732
733 template <class T>
eval_bitwise_xor_default(T & t,const T & u,const T & v)734 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const T& u, const T& v)
735 {
736 if (&t == &v)
737 {
738 eval_bitwise_xor(t, u);
739 }
740 else if (&t == &u)
741 {
742 eval_bitwise_xor(t, v);
743 }
744 else
745 {
746 t = u;
747 eval_bitwise_xor(t, v);
748 }
749 }
750 template <class T, class U>
eval_bitwise_xor_default(T & t,const T & u,const U & v)751 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
752 {
753 T vv;
754 vv = v;
755 eval_bitwise_xor(t, u, vv);
756 }
757 template <class T, class U>
eval_bitwise_xor_default(T & t,const T & u,const U & v)758 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
759 {
760 T vv(v);
761 eval_bitwise_xor(t, u, vv);
762 }
763 template <class T, class U>
eval_bitwise_xor_default(T & t,const U & u,const T & v)764 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v)
765 {
766 eval_bitwise_xor(t, v, u);
767 }
768 template <class T, class U, class V>
eval_bitwise_xor_default(T & t,const U & u,const V & v)769 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor_default(T& t, const U& u, const V& v)
770 {
771 if (is_same<T, V>::value && ((void*)&t == (void*)&v))
772 {
773 eval_bitwise_xor(t, u);
774 }
775 else
776 {
777 t = u;
778 eval_bitwise_xor(t, v);
779 }
780 }
781 template <class T, class U, class V>
eval_bitwise_xor(T & t,const U & u,const V & v)782 inline BOOST_MP_CXX14_CONSTEXPR void eval_bitwise_xor(T& t, const U& u, const V& v)
783 {
784 eval_bitwise_xor_default(t, u, v);
785 }
786
787 template <class T>
eval_increment(T & val)788 inline BOOST_MP_CXX14_CONSTEXPR void eval_increment(T& val)
789 {
790 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
791 eval_add(val, static_cast<ui_type>(1u));
792 }
793 template <class T>
eval_decrement(T & val)794 inline BOOST_MP_CXX14_CONSTEXPR void eval_decrement(T& val)
795 {
796 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
797 eval_subtract(val, static_cast<ui_type>(1u));
798 }
799
800 template <class T, class V>
eval_left_shift(T & result,const T & arg,const V val)801 inline BOOST_MP_CXX14_CONSTEXPR void eval_left_shift(T& result, const T& arg, const V val)
802 {
803 result = arg;
804 eval_left_shift(result, val);
805 }
806
807 template <class T, class V>
eval_right_shift(T & result,const T & arg,const V val)808 inline BOOST_MP_CXX14_CONSTEXPR void eval_right_shift(T& result, const T& arg, const V val)
809 {
810 result = arg;
811 eval_right_shift(result, val);
812 }
813
814 template <class T>
eval_is_zero(const T & val)815 inline BOOST_MP_CXX14_CONSTEXPR bool eval_is_zero(const T& val)
816 {
817 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
818 return val.compare(static_cast<ui_type>(0)) == 0;
819 }
820 template <class T>
eval_get_sign(const T & val)821 inline BOOST_MP_CXX14_CONSTEXPR int eval_get_sign(const T& val)
822 {
823 typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
824 return val.compare(static_cast<ui_type>(0));
825 }
826
827 template <class T, class V, class U>
assign_components_imp(T & result,const V & v1,const U & v2,const mpl::int_<number_kind_rational> &)828 inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const mpl::int_<number_kind_rational>&)
829 {
830 result = v1;
831 T t;
832 t = v2;
833 eval_divide(result, t);
834 }
835
836 template <class T, class V, class U, int N>
assign_components_imp(T & result,const V & v1,const U & v2,const mpl::int_<N> &)837 inline BOOST_MP_CXX14_CONSTEXPR void assign_components_imp(T& result, const V& v1, const U& v2, const mpl::int_<N>&)
838 {
839 typedef typename component_type<number<T> >::type component_number_type;
840
841 component_number_type x(v1), y(v2);
842 assign_components(result, x.backend(), y.backend());
843 }
844
845 template <class T, class V, class U>
assign_components(T & result,const V & v1,const U & v2)846 inline BOOST_MP_CXX14_CONSTEXPR void assign_components(T& result, const V& v1, const U& v2)
847 {
848 return assign_components_imp(result, v1, v2, typename number_category<T>::type());
849 }
850 #ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
851 template <class Result, class Traits>
assign_from_string_view(Result & result,const std::basic_string_view<char,Traits> & view)852 inline void assign_from_string_view(Result& result, const std::basic_string_view<char, Traits>& view)
853 {
854 // since most (all?) backends require a const char* to construct from, we just
855 // convert to that:
856 std::string s(view);
857 result = s.c_str();
858 }
859 template <class Result, class Traits>
assign_from_string_view(Result & result,const std::basic_string_view<char,Traits> & view_x,const std::basic_string_view<char,Traits> & view_y)860 inline void assign_from_string_view(Result& result, const std::basic_string_view<char, Traits>& view_x, const std::basic_string_view<char, Traits>& view_y)
861 {
862 // since most (all?) backends require a const char* to construct from, we just
863 // convert to that:
864 std::string x(view_x), y(view_y);
865 assign_components(result, x.c_str(), y.c_str());
866 }
867 #endif
868 template <class R, int b>
869 struct has_enough_bits
870 {
871 template <class T>
872 struct type : public mpl::and_<mpl::not_<is_same<R, T> >, mpl::bool_<std::numeric_limits<T>::digits >= b> >
873 {};
874 };
875
876 template <class R>
877 struct terminal
878 {
terminalboost::multiprecision::default_ops::terminal879 BOOST_MP_CXX14_CONSTEXPR terminal(const R& v) : value(v) {}
terminalboost::multiprecision::default_ops::terminal880 BOOST_MP_CXX14_CONSTEXPR terminal() {}
operator =boost::multiprecision::default_ops::terminal881 BOOST_MP_CXX14_CONSTEXPR terminal& operator=(R val)
882 {
883 value = val;
884 return *this;
885 }
886 R value;
operator Rboost::multiprecision::default_ops::terminal887 BOOST_MP_CXX14_CONSTEXPR operator R() const { return value; }
888 };
889
890 template <class R, class B>
891 struct calculate_next_larger_type
892 {
893 // Find which list we're looking through:
894 typedef typename mpl::if_<
895 is_signed<R>,
896 typename B::signed_types,
897 typename mpl::if_<
898 is_unsigned<R>,
899 typename B::unsigned_types,
900 typename B::float_types>::type>::type list_type;
901 // A predicate to find a type with enough bits:
902 typedef typename has_enough_bits<R, std::numeric_limits<R>::digits>::template type<mpl::_> pred_type;
903 // See if the last type is in the list, if so we have to start after this:
904 typedef typename mpl::find_if<
905 list_type,
906 is_same<R, mpl::_> >::type start_last;
907 // Where we're starting from, either the start of the sequence or the last type found:
908 typedef typename mpl::if_<is_same<start_last, typename mpl::end<list_type>::type>, typename mpl::begin<list_type>::type, start_last>::type start_seq;
909 // The range we're searching:
910 typedef mpl::iterator_range<start_seq, typename mpl::end<list_type>::type> range;
911 // Find the next type:
912 typedef typename mpl::find_if<
913 range,
914 pred_type>::type iter_type;
915 // Either the next type, or a "terminal" to indicate we've run out of types to search:
916 typedef typename mpl::eval_if<
917 is_same<typename mpl::end<list_type>::type, iter_type>,
918 mpl::identity<terminal<R> >,
919 mpl::deref<iter_type> >::type type;
920 };
921
922 template <class R, class T>
check_in_range(const T & t)923 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_integral<R>::value, bool>::type check_in_range(const T& t)
924 {
925 // Can t fit in an R?
926 if ((t > 0) && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)()))
927 return true;
928 else
929 return false;
930 }
931
932 template <class R, class B>
eval_convert_to(R * result,const B & backend)933 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend)
934 {
935 typedef typename calculate_next_larger_type<R, B>::type next_type;
936 next_type n = next_type();
937 eval_convert_to(&n, backend);
938 if (!boost::is_unsigned<R>::value && std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (n > (next_type)(std::numeric_limits<R>::max)()))
939 {
940 *result = (std::numeric_limits<R>::max)();
941 }
942 else if (std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (n < (next_type)(std::numeric_limits<R>::min)()))
943 {
944 *result = (std::numeric_limits<R>::min)();
945 }
946 else
947 *result = static_cast<R>(n);
948 }
949
950 template <class R, class B>
eval_convert_to(R * result,const B & backend)951 inline BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<boost::is_integral<R>::value>::type eval_convert_to(R* result, const B& backend)
952 {
953 typedef typename calculate_next_larger_type<R, B>::type next_type;
954 next_type n = next_type();
955 eval_convert_to(&n, backend);
956 if (std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && ((n > (next_type)(std::numeric_limits<R>::max)() || (n < (next_type) - (std::numeric_limits<R>::max)()))))
957 {
958 *result = n > 0 ? (std::numeric_limits<R>::max)() : -(std::numeric_limits<R>::max)();
959 }
960 else
961 *result = static_cast<R>(n);
962 }
963
964 template <class R, class B>
last_chance_eval_convert_to(terminal<R> * result,const B & backend,const mpl::false_ &)965 inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const mpl::false_&)
966 {
967 //
968 // We ran out of types to try for the conversion, try
969 // a lexical_cast and hope for the best:
970 //
971 if (std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed && (eval_get_sign(backend) < 0))
972 BOOST_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
973 try
974 {
975 result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0)));
976 }
977 catch (const bad_lexical_cast&)
978 {
979 if (eval_get_sign(backend) < 0)
980 {
981 *result = std::numeric_limits<R>::is_integer && std::numeric_limits<R>::is_signed ? (std::numeric_limits<R>::min)() : -(std::numeric_limits<R>::max)();
982 }
983 else
984 *result = (std::numeric_limits<R>::max)();
985 }
986 }
987
988 template <class R, class B>
last_chance_eval_convert_to(terminal<R> * result,const B & backend,const mpl::true_ &)989 inline void last_chance_eval_convert_to(terminal<R>* result, const B& backend, const mpl::true_&)
990 {
991 //
992 // We ran out of types to try for the conversion, try
993 // a lexical_cast and hope for the best:
994 //
995 if (std::numeric_limits<R>::is_integer && !std::numeric_limits<R>::is_signed && (eval_get_sign(backend) < 0))
996 BOOST_THROW_EXCEPTION(std::range_error("Attempt to convert negative value to an unsigned integer results in undefined behaviour"));
997 try
998 {
999 B t(backend);
1000 R mask = ~static_cast<R>(0u);
1001 eval_bitwise_and(t, mask);
1002 result->value = boost::lexical_cast<R>(t.str(0, std::ios_base::fmtflags(0)));
1003 }
1004 catch (const bad_lexical_cast&)
1005 {
1006 if (eval_get_sign(backend) < 0)
1007 {
1008 *result = std::numeric_limits<R>::is_integer && std::numeric_limits<R>::is_signed ? (std::numeric_limits<R>::min)() : -(std::numeric_limits<R>::max)();
1009 }
1010 else
1011 *result = (std::numeric_limits<R>::max)();
1012 }
1013 }
1014
1015 template <class R, class B>
eval_convert_to(terminal<R> * result,const B & backend)1016 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<R>* result, const B& backend)
1017 {
1018 typedef mpl::bool_<boost::is_unsigned<R>::value && number_category<B>::value == number_kind_integer> tag_type;
1019 last_chance_eval_convert_to(result, backend, tag_type());
1020 }
1021
1022 template <class B1, class B2, expression_template_option et>
eval_convert_to(terminal<number<B1,et>> * result,const B2 & backend)1023 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(terminal<number<B1, et> >* result, const B2& backend)
1024 {
1025 //
1026 // We ran out of types to try for the conversion, try
1027 // a generic conversion and hope for the best:
1028 //
1029 boost::multiprecision::detail::generic_interconvert(result->value.backend(), backend, number_category<B1>(), number_category<B2>());
1030 }
1031
1032 template <class B>
eval_convert_to(std::string * result,const B & backend)1033 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::string* result, const B& backend)
1034 {
1035 *result = backend.str(0, std::ios_base::fmtflags(0));
1036 }
1037
1038 template <class B>
eval_convert_to(std::complex<float> * result,const B & backend)1039 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<float>* result, const B& backend)
1040 {
1041 typedef typename scalar_result_from_possible_complex<multiprecision::number<B> >::type scalar_type;
1042 scalar_type re, im;
1043 eval_real(re.backend(), backend);
1044 eval_imag(im.backend(), backend);
1045
1046 *result = std::complex<float>(re.template convert_to<float>(), im.template convert_to<float>());
1047 }
1048
1049 template <class B>
eval_convert_to(std::complex<double> * result,const B & backend)1050 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<double>* result, const B& backend)
1051 {
1052 typedef typename scalar_result_from_possible_complex<multiprecision::number<B> >::type scalar_type;
1053 scalar_type re, im;
1054 eval_real(re.backend(), backend);
1055 eval_imag(im.backend(), backend);
1056
1057 *result = std::complex<double>(re.template convert_to<double>(), im.template convert_to<double>());
1058 }
1059
1060 template <class B>
eval_convert_to(std::complex<long double> * result,const B & backend)1061 inline BOOST_MP_CXX14_CONSTEXPR void eval_convert_to(std::complex<long double>* result, const B& backend)
1062 {
1063 typedef typename scalar_result_from_possible_complex<multiprecision::number<B> >::type scalar_type;
1064 scalar_type re, im;
1065 eval_real(re.backend(), backend);
1066 eval_imag(im.backend(), backend);
1067
1068 *result = std::complex<long double>(re.template convert_to<long double>(), im.template convert_to<long double>());
1069 }
1070
1071 //
1072 // Functions:
1073 //
1074 template <class T>
eval_abs(T & result,const T & arg)1075 inline BOOST_MP_CXX14_CONSTEXPR void eval_abs(T& result, const T& arg)
1076 {
1077 typedef typename T::signed_types type_list;
1078 typedef typename mpl::front<type_list>::type front;
1079 result = arg;
1080 if (arg.compare(front(0)) < 0)
1081 result.negate();
1082 }
1083 template <class T>
eval_fabs(T & result,const T & arg)1084 inline BOOST_MP_CXX14_CONSTEXPR void eval_fabs(T& result, const T& arg)
1085 {
1086 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The fabs function is only valid for floating point types.");
1087 typedef typename T::signed_types type_list;
1088 typedef typename mpl::front<type_list>::type front;
1089 result = arg;
1090 if (arg.compare(front(0)) < 0)
1091 result.negate();
1092 }
1093
1094 template <class Backend>
eval_fpclassify(const Backend & arg)1095 inline BOOST_MP_CXX14_CONSTEXPR int eval_fpclassify(const Backend& arg)
1096 {
1097 BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types.");
1098 return eval_is_zero(arg) ? FP_ZERO : FP_NORMAL;
1099 }
1100
1101 template <class T>
eval_fmod(T & result,const T & a,const T & b)1102 inline BOOST_MP_CXX14_CONSTEXPR void eval_fmod(T& result, const T& a, const T& b)
1103 {
1104 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The fmod function is only valid for floating point types.");
1105 if ((&result == &a) || (&result == &b))
1106 {
1107 T temp;
1108 eval_fmod(temp, a, b);
1109 result = temp;
1110 return;
1111 }
1112 switch (eval_fpclassify(a))
1113 {
1114 case FP_ZERO:
1115 result = a;
1116 return;
1117 case FP_INFINITE:
1118 case FP_NAN:
1119 result = std::numeric_limits<number<T> >::quiet_NaN().backend();
1120 errno = EDOM;
1121 return;
1122 }
1123 switch (eval_fpclassify(b))
1124 {
1125 case FP_ZERO:
1126 case FP_NAN:
1127 result = std::numeric_limits<number<T> >::quiet_NaN().backend();
1128 errno = EDOM;
1129 return;
1130 }
1131 T n;
1132 eval_divide(result, a, b);
1133 if (eval_get_sign(result) < 0)
1134 eval_ceil(n, result);
1135 else
1136 eval_floor(n, result);
1137 eval_multiply(n, b);
1138 eval_subtract(result, a, n);
1139 }
1140 template <class T, class A>
eval_fmod(T & result,const T & x,const A & a)1141 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const T& x, const A& a)
1142 {
1143 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
1144 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
1145 cast_type c;
1146 c = a;
1147 eval_fmod(result, x, c);
1148 }
1149
1150 template <class T, class A>
eval_fmod(T & result,const A & x,const T & a)1151 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const A& x, const T& a)
1152 {
1153 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
1154 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
1155 cast_type c;
1156 c = x;
1157 eval_fmod(result, c, a);
1158 }
1159
1160 template <class T>
1161 BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a);
1162
1163 template <class T>
eval_remquo(T & result,const T & a,const T & b,int * pi)1164 inline BOOST_MP_CXX14_CONSTEXPR void eval_remquo(T& result, const T& a, const T& b, int* pi)
1165 {
1166 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The remquo function is only valid for floating point types.");
1167 if ((&result == &a) || (&result == &b))
1168 {
1169 T temp;
1170 eval_remquo(temp, a, b, pi);
1171 result = temp;
1172 return;
1173 }
1174 T n;
1175 eval_divide(result, a, b);
1176 eval_round(n, result);
1177 eval_convert_to(pi, n);
1178 eval_multiply(n, b);
1179 eval_subtract(result, a, n);
1180 }
1181 template <class T, class A>
eval_remquo(T & result,const T & x,const A & a,int * pi)1182 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, void>::type eval_remquo(T& result, const T& x, const A& a, int* pi)
1183 {
1184 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
1185 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
1186 cast_type c = cast_type();
1187 c = a;
1188 eval_remquo(result, x, c, pi);
1189 }
1190 template <class T, class A>
eval_remquo(T & result,const A & x,const T & a,int * pi)1191 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_arithmetic<A>, void>::type eval_remquo(T& result, const A& x, const T& a, int* pi)
1192 {
1193 typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
1194 typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
1195 cast_type c = cast_type();
1196 c = x;
1197 eval_remquo(result, c, a, pi);
1198 }
1199 template <class T, class U, class V>
eval_remainder(T & result,const U & a,const V & b)1200 inline BOOST_MP_CXX14_CONSTEXPR void eval_remainder(T& result, const U& a, const V& b)
1201 {
1202 int i(0);
1203 eval_remquo(result, a, b, &i);
1204 }
1205
1206 template <class B>
1207 BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const B& a, const B& b);
1208 template <class T, class U>
1209 BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const T& a, const U& b);
1210 template <class B>
1211 BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const B& a, const B& b);
1212 template <class T, class U>
1213 BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const T& a, const U& b);
1214
1215 template <class T>
eval_fdim(T & result,const T & a,const T & b)1216 inline BOOST_MP_CXX14_CONSTEXPR void eval_fdim(T& result, const T& a, const T& b)
1217 {
1218 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1219 const ui_type zero = 0u;
1220 switch (eval_fpclassify(b))
1221 {
1222 case FP_NAN:
1223 case FP_INFINITE:
1224 result = zero;
1225 return;
1226 }
1227 switch (eval_fpclassify(a))
1228 {
1229 case FP_NAN:
1230 result = zero;
1231 return;
1232 case FP_INFINITE:
1233 result = a;
1234 return;
1235 }
1236 if (eval_gt(a, b))
1237 {
1238 eval_subtract(result, a, b);
1239 }
1240 else
1241 result = zero;
1242 }
1243
1244 template <class T, class A>
eval_fdim(T & result,const T & a,const A & b)1245 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fdim(T& result, const T& a, const A& b)
1246 {
1247 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1248 typedef typename boost::multiprecision::detail::canonical<A, T>::type arithmetic_type;
1249 const ui_type zero = 0u;
1250 arithmetic_type canonical_b = b;
1251 switch ((::boost::math::fpclassify)(b))
1252 {
1253 case FP_NAN:
1254 case FP_INFINITE:
1255 result = zero;
1256 return;
1257 }
1258 switch (eval_fpclassify(a))
1259 {
1260 case FP_NAN:
1261 result = zero;
1262 return;
1263 case FP_INFINITE:
1264 result = a;
1265 return;
1266 }
1267 if (eval_gt(a, canonical_b))
1268 {
1269 eval_subtract(result, a, canonical_b);
1270 }
1271 else
1272 result = zero;
1273 }
1274
1275 template <class T, class A>
eval_fdim(T & result,const A & a,const T & b)1276 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_arithmetic<A>::value>::type eval_fdim(T& result, const A& a, const T& b)
1277 {
1278 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1279 typedef typename boost::multiprecision::detail::canonical<A, T>::type arithmetic_type;
1280 const ui_type zero = 0u;
1281 arithmetic_type canonical_a = a;
1282 switch (eval_fpclassify(b))
1283 {
1284 case FP_NAN:
1285 case FP_INFINITE:
1286 result = zero;
1287 return;
1288 }
1289 switch ((::boost::math::fpclassify)(a))
1290 {
1291 case FP_NAN:
1292 result = zero;
1293 return;
1294 case FP_INFINITE:
1295 result = std::numeric_limits<number<T> >::infinity().backend();
1296 return;
1297 }
1298 if (eval_gt(canonical_a, b))
1299 {
1300 eval_subtract(result, canonical_a, b);
1301 }
1302 else
1303 result = zero;
1304 }
1305
1306 template <class T>
eval_trunc(T & result,const T & a)1307 inline BOOST_MP_CXX14_CONSTEXPR void eval_trunc(T& result, const T& a)
1308 {
1309 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
1310 switch (eval_fpclassify(a))
1311 {
1312 case FP_NAN:
1313 errno = EDOM;
1314 // fallthrough...
1315 case FP_ZERO:
1316 case FP_INFINITE:
1317 result = a;
1318 return;
1319 }
1320 if (eval_get_sign(a) < 0)
1321 eval_ceil(result, a);
1322 else
1323 eval_floor(result, a);
1324 }
1325
1326 template <class T>
eval_modf(T & result,T const & arg,T * pipart)1327 inline BOOST_MP_CXX14_CONSTEXPR void eval_modf(T& result, T const& arg, T* pipart)
1328 {
1329 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1330 int c = eval_fpclassify(arg);
1331 if (c == (int)FP_NAN)
1332 {
1333 if (pipart)
1334 *pipart = arg;
1335 result = arg;
1336 return;
1337 }
1338 else if (c == (int)FP_INFINITE)
1339 {
1340 if (pipart)
1341 *pipart = arg;
1342 result = ui_type(0u);
1343 return;
1344 }
1345 if (pipart)
1346 {
1347 eval_trunc(*pipart, arg);
1348 eval_subtract(result, arg, *pipart);
1349 }
1350 else
1351 {
1352 T ipart;
1353 eval_trunc(ipart, arg);
1354 eval_subtract(result, arg, ipart);
1355 }
1356 }
1357
1358 template <class T>
eval_round(T & result,const T & a)1359 inline BOOST_MP_CXX14_CONSTEXPR void eval_round(T& result, const T& a)
1360 {
1361 BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
1362 typedef typename boost::multiprecision::detail::canonical<float, T>::type fp_type;
1363 int c = eval_fpclassify(a);
1364 if (c == (int)FP_NAN)
1365 {
1366 result = a;
1367 errno = EDOM;
1368 return;
1369 }
1370 if ((c == FP_ZERO) || (c == (int)FP_INFINITE))
1371 {
1372 result = a;
1373 }
1374 else if (eval_get_sign(a) < 0)
1375 {
1376 eval_subtract(result, a, fp_type(0.5f));
1377 eval_ceil(result, result);
1378 }
1379 else
1380 {
1381 eval_add(result, a, fp_type(0.5f));
1382 eval_floor(result, result);
1383 }
1384 }
1385
1386 template <class B>
1387 BOOST_MP_CXX14_CONSTEXPR void eval_lcm(B& result, const B& a, const B& b);
1388 template <class B>
1389 BOOST_MP_CXX14_CONSTEXPR void eval_gcd(B& result, const B& a, const B& b);
1390
1391 template <class T, class Arithmetic>
eval_gcd(T & result,const T & a,const Arithmetic & b)1392 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const T& a, const Arithmetic& b)
1393 {
1394 typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
1395 using default_ops::eval_gcd;
1396 T t;
1397 t = static_cast<si_type>(b);
1398 eval_gcd(result, a, t);
1399 }
1400 template <class T, class Arithmetic>
eval_gcd(T & result,const Arithmetic & a,const T & b)1401 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const Arithmetic& a, const T& b)
1402 {
1403 eval_gcd(result, b, a);
1404 }
1405 template <class T, class Arithmetic>
eval_lcm(T & result,const T & a,const Arithmetic & b)1406 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const T& a, const Arithmetic& b)
1407 {
1408 typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
1409 using default_ops::eval_lcm;
1410 T t;
1411 t = static_cast<si_type>(b);
1412 eval_lcm(result, a, t);
1413 }
1414 template <class T, class Arithmetic>
eval_lcm(T & result,const Arithmetic & a,const T & b)1415 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const Arithmetic& a, const T& b)
1416 {
1417 eval_lcm(result, b, a);
1418 }
1419
1420 template <class T>
eval_lsb(const T & val)1421 inline BOOST_MP_CXX14_CONSTEXPR unsigned eval_lsb(const T& val)
1422 {
1423 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1424 int c = eval_get_sign(val);
1425 if (c == 0)
1426 {
1427 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
1428 }
1429 if (c < 0)
1430 {
1431 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
1432 }
1433 unsigned result = 0;
1434 T mask, t;
1435 mask = ui_type(1);
1436 do
1437 {
1438 eval_bitwise_and(t, mask, val);
1439 ++result;
1440 eval_left_shift(mask, 1);
1441 } while (eval_is_zero(t));
1442
1443 return --result;
1444 }
1445
1446 template <class T>
eval_msb(const T & val)1447 inline BOOST_MP_CXX14_CONSTEXPR int eval_msb(const T& val)
1448 {
1449 int c = eval_get_sign(val);
1450 if (c == 0)
1451 {
1452 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
1453 }
1454 if (c < 0)
1455 {
1456 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
1457 }
1458 //
1459 // This implementation is really really rubbish - it does
1460 // a linear scan for the most-significant-bit. We should really
1461 // do a binary search, but as none of our backends actually needs
1462 // this implementation, we'll leave it for now. In fact for most
1463 // backends it's likely that there will always be a more efficient
1464 // native implementation possible.
1465 //
1466 unsigned result = 0;
1467 T t(val);
1468 while (!eval_is_zero(t))
1469 {
1470 eval_right_shift(t, 1);
1471 ++result;
1472 }
1473 return --result;
1474 }
1475
1476 template <class T>
eval_bit_test(const T & val,unsigned index)1477 inline BOOST_MP_CXX14_CONSTEXPR bool eval_bit_test(const T& val, unsigned index)
1478 {
1479 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1480 T mask, t;
1481 mask = ui_type(1);
1482 eval_left_shift(mask, index);
1483 eval_bitwise_and(t, mask, val);
1484 return !eval_is_zero(t);
1485 }
1486
1487 template <class T>
eval_bit_set(T & val,unsigned index)1488 inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_set(T& val, unsigned index)
1489 {
1490 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1491 T mask;
1492 mask = ui_type(1);
1493 eval_left_shift(mask, index);
1494 eval_bitwise_or(val, mask);
1495 }
1496
1497 template <class T>
eval_bit_flip(T & val,unsigned index)1498 inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_flip(T& val, unsigned index)
1499 {
1500 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1501 T mask;
1502 mask = ui_type(1);
1503 eval_left_shift(mask, index);
1504 eval_bitwise_xor(val, mask);
1505 }
1506
1507 template <class T>
eval_bit_unset(T & val,unsigned index)1508 inline BOOST_MP_CXX14_CONSTEXPR void eval_bit_unset(T& val, unsigned index)
1509 {
1510 typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
1511 T mask, t;
1512 mask = ui_type(1);
1513 eval_left_shift(mask, index);
1514 eval_bitwise_and(t, mask, val);
1515 if (!eval_is_zero(t))
1516 eval_bitwise_xor(val, mask);
1517 }
1518
1519 template <class B>
eval_integer_sqrt(B & s,B & r,const B & x)1520 void BOOST_MP_CXX14_CONSTEXPR eval_integer_sqrt(B& s, B& r, const B& x)
1521 {
1522 //
1523 // This is slow bit-by-bit integer square root, see for example
1524 // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
1525 // There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf
1526 // and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented
1527 // at some point.
1528 //
1529 typedef typename boost::multiprecision::detail::canonical<unsigned char, B>::type ui_type;
1530
1531 s = ui_type(0u);
1532 if (eval_get_sign(x) == 0)
1533 {
1534 r = ui_type(0u);
1535 return;
1536 }
1537 int g = eval_msb(x);
1538 if (g <= 1)
1539 {
1540 s = ui_type(1);
1541 eval_subtract(r, x, s);
1542 return;
1543 }
1544
1545 B t;
1546 r = x;
1547 g /= 2;
1548 int org_g = g;
1549 eval_bit_set(s, g);
1550 eval_bit_set(t, 2 * g);
1551 eval_subtract(r, x, t);
1552 --g;
1553 if (eval_get_sign(r) == 0)
1554 return;
1555 int msbr = eval_msb(r);
1556 do
1557 {
1558 if (msbr >= org_g + g + 1)
1559 {
1560 t = s;
1561 eval_left_shift(t, g + 1);
1562 eval_bit_set(t, 2 * g);
1563 if (t.compare(r) <= 0)
1564 {
1565 BOOST_ASSERT(g >= 0);
1566 eval_bit_set(s, g);
1567 eval_subtract(r, t);
1568 if (eval_get_sign(r) == 0)
1569 return;
1570 msbr = eval_msb(r);
1571 }
1572 }
1573 --g;
1574 } while (g >= 0);
1575 }
1576
1577 template <class B>
eval_conj(B & result,const B & val)1578 inline BOOST_MP_CXX14_CONSTEXPR void eval_conj(B& result, const B& val)
1579 {
1580 result = val; // assume non-complex result.
1581 }
1582 template <class B>
eval_proj(B & result,const B & val)1583 inline BOOST_MP_CXX14_CONSTEXPR void eval_proj(B& result, const B& val)
1584 {
1585 result = val; // assume non-complex result.
1586 }
1587
1588 //
1589 // These have to implemented by the backend, declared here so that our macro generated code compiles OK.
1590 //
1591 template <class T>
1592 typename enable_if_c<sizeof(T) == 0>::type eval_floor();
1593 template <class T>
1594 typename enable_if_c<sizeof(T) == 0>::type eval_ceil();
1595 template <class T>
1596 typename enable_if_c<sizeof(T) == 0>::type eval_trunc();
1597 template <class T>
1598 typename enable_if_c<sizeof(T) == 0>::type eval_sqrt();
1599 template <class T>
1600 typename enable_if_c<sizeof(T) == 0>::type eval_ldexp();
1601 template <class T>
1602 typename enable_if_c<sizeof(T) == 0>::type eval_frexp();
1603 // TODO implement default versions of these:
1604 template <class T>
1605 typename enable_if_c<sizeof(T) == 0>::type eval_asinh();
1606 template <class T>
1607 typename enable_if_c<sizeof(T) == 0>::type eval_acosh();
1608 template <class T>
1609 typename enable_if_c<sizeof(T) == 0>::type eval_atanh();
1610
1611 //
1612 // eval_logb and eval_scalbn simply assume base 2 and forward to
1613 // eval_ldexp and eval_frexp:
1614 //
1615 template <class B>
eval_ilogb(const B & val)1616 inline BOOST_MP_CXX14_CONSTEXPR typename B::exponent_type eval_ilogb(const B& val)
1617 {
1618 BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of ilogb requires a base 2 number type");
1619 typename B::exponent_type e(0);
1620 switch (eval_fpclassify(val))
1621 {
1622 case FP_NAN:
1623 #ifdef FP_ILOGBNAN
1624 return FP_ILOGBNAN > 0 ? (std::numeric_limits<typename B::exponent_type>::max)() : (std::numeric_limits<typename B::exponent_type>::min)();
1625 #else
1626 return (std::numeric_limits<typename B::exponent_type>::max)();
1627 #endif
1628 case FP_INFINITE:
1629 return (std::numeric_limits<typename B::exponent_type>::max)();
1630 case FP_ZERO:
1631 return (std::numeric_limits<typename B::exponent_type>::min)();
1632 }
1633 B result;
1634 eval_frexp(result, val, &e);
1635 return e - 1;
1636 }
1637
1638 template <class T>
1639 BOOST_MP_CXX14_CONSTEXPR int eval_signbit(const T& val);
1640
1641 template <class B>
eval_logb(B & result,const B & val)1642 inline BOOST_MP_CXX14_CONSTEXPR void eval_logb(B& result, const B& val)
1643 {
1644 switch (eval_fpclassify(val))
1645 {
1646 case FP_NAN:
1647 result = val;
1648 errno = EDOM;
1649 return;
1650 case FP_ZERO:
1651 result = std::numeric_limits<number<B> >::infinity().backend();
1652 result.negate();
1653 errno = ERANGE;
1654 return;
1655 case FP_INFINITE:
1656 result = val;
1657 if (eval_signbit(val))
1658 result.negate();
1659 return;
1660 }
1661 typedef typename boost::mpl::if_c<boost::is_same<boost::intmax_t, long>::value, boost::long_long_type, boost::intmax_t>::type max_t;
1662 result = static_cast<max_t>(eval_ilogb(val));
1663 }
1664 template <class B, class A>
eval_scalbn(B & result,const B & val,A e)1665 inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbn(B& result, const B& val, A e)
1666 {
1667 BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of scalbn requires a base 2 number type");
1668 eval_ldexp(result, val, static_cast<typename B::exponent_type>(e));
1669 }
1670 template <class B, class A>
eval_scalbln(B & result,const B & val,A e)1671 inline BOOST_MP_CXX14_CONSTEXPR void eval_scalbln(B& result, const B& val, A e)
1672 {
1673 eval_scalbn(result, val, e);
1674 }
1675
1676 template <class T>
is_arg_nan(const T & val,mpl::true_ const &,const mpl::false_ &)1677 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, mpl::true_ const&, const mpl::false_&)
1678 {
1679 return eval_fpclassify(val) == FP_NAN;
1680 }
1681 template <class T>
is_arg_nan(const T & val,mpl::false_ const &,const mpl::true_ &)1682 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val, mpl::false_ const&, const mpl::true_&)
1683 {
1684 return (boost::math::isnan)(val);
1685 }
1686 template <class T>
is_arg_nan(const T &,mpl::false_ const &,const mpl::false_ &)1687 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T&, mpl::false_ const&, const mpl::false_&)
1688 {
1689 return false;
1690 }
1691
1692 template <class T>
is_arg_nan(const T & val)1693 inline BOOST_MP_CXX14_CONSTEXPR bool is_arg_nan(const T& val)
1694 {
1695 return is_arg_nan(val, mpl::bool_<boost::multiprecision::detail::is_backend<T>::value>(), is_floating_point<T>());
1696 }
1697
1698 template <class T, class U, class V>
eval_fmax(T & result,const U & a,const V & b)1699 inline BOOST_MP_CXX14_CONSTEXPR void eval_fmax(T& result, const U& a, const V& b)
1700 {
1701 if (is_arg_nan(a))
1702 result = number<T>::canonical_value(b);
1703 else if (is_arg_nan(b))
1704 result = number<T>::canonical_value(a);
1705 else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
1706 result = number<T>::canonical_value(b);
1707 else
1708 result = number<T>::canonical_value(a);
1709 }
1710 template <class T, class U, class V>
eval_fmin(T & result,const U & a,const V & b)1711 inline BOOST_MP_CXX14_CONSTEXPR void eval_fmin(T& result, const U& a, const V& b)
1712 {
1713 if (is_arg_nan(a))
1714 result = number<T>::canonical_value(b);
1715 else if (is_arg_nan(b))
1716 result = number<T>::canonical_value(a);
1717 else if (eval_lt(number<T>::canonical_value(a), number<T>::canonical_value(b)))
1718 result = number<T>::canonical_value(a);
1719 else
1720 result = number<T>::canonical_value(b);
1721 }
1722
1723 template <class R, class T, class U>
eval_hypot(R & result,const T & a,const U & b)1724 inline BOOST_MP_CXX14_CONSTEXPR void eval_hypot(R& result, const T& a, const U& b)
1725 {
1726 //
1727 // Normalize x and y, so that both are positive and x >= y:
1728 //
1729 R x, y;
1730 x = number<R>::canonical_value(a);
1731 y = number<R>::canonical_value(b);
1732 if (eval_get_sign(x) < 0)
1733 x.negate();
1734 if (eval_get_sign(y) < 0)
1735 y.negate();
1736
1737 // Special case, see C99 Annex F.
1738 // The order of the if's is important: do not change!
1739 int c1 = eval_fpclassify(x);
1740 int c2 = eval_fpclassify(y);
1741
1742 if (c1 == FP_ZERO)
1743 {
1744 result = y;
1745 return;
1746 }
1747 if (c2 == FP_ZERO)
1748 {
1749 result = x;
1750 return;
1751 }
1752 if (c1 == FP_INFINITE)
1753 {
1754 result = x;
1755 return;
1756 }
1757 if ((c2 == FP_INFINITE) || (c2 == FP_NAN))
1758 {
1759 result = y;
1760 return;
1761 }
1762 if (c1 == FP_NAN)
1763 {
1764 result = x;
1765 return;
1766 }
1767
1768 if (eval_gt(y, x))
1769 x.swap(y);
1770
1771 eval_multiply(result, x, std::numeric_limits<number<R> >::epsilon().backend());
1772
1773 if (eval_gt(result, y))
1774 {
1775 result = x;
1776 return;
1777 }
1778
1779 R rat;
1780 eval_divide(rat, y, x);
1781 eval_multiply(result, rat, rat);
1782 eval_increment(result);
1783 eval_sqrt(rat, result);
1784 eval_multiply(result, rat, x);
1785 }
1786
1787 template <class R, class T>
eval_nearbyint(R & result,const T & a)1788 inline BOOST_MP_CXX14_CONSTEXPR void eval_nearbyint(R& result, const T& a)
1789 {
1790 eval_round(result, a);
1791 }
1792 template <class R, class T>
eval_rint(R & result,const T & a)1793 inline BOOST_MP_CXX14_CONSTEXPR void eval_rint(R& result, const T& a)
1794 {
1795 eval_nearbyint(result, a);
1796 }
1797
1798 template <class T>
eval_signbit(const T & val)1799 inline BOOST_MP_CXX14_CONSTEXPR int eval_signbit(const T& val)
1800 {
1801 return eval_get_sign(val) < 0 ? 1 : 0;
1802 }
1803
1804 //
1805 // Real and imaginary parts:
1806 //
1807 template <class To, class From>
eval_real(To & to,const From & from)1808 inline BOOST_MP_CXX14_CONSTEXPR void eval_real(To& to, const From& from)
1809 {
1810 to = from;
1811 }
1812 template <class To, class From>
eval_imag(To & to,const From &)1813 inline BOOST_MP_CXX14_CONSTEXPR void eval_imag(To& to, const From&)
1814 {
1815 typedef typename mpl::front<typename To::unsigned_types>::type ui_type;
1816 to = ui_type(0);
1817 }
1818
1819 } // namespace default_ops
1820 namespace default_ops_adl {
1821
1822 template <class To, class From>
eval_set_real_imp(To & to,const From & from)1823 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real_imp(To& to, const From& from)
1824 {
1825 typedef typename component_type<number<To> >::type to_component_type;
1826 typename to_component_type::backend_type to_component;
1827 to_component = from;
1828 eval_set_real(to, to_component);
1829 }
1830 template <class To, class From>
eval_set_imag_imp(To & to,const From & from)1831 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag_imp(To& to, const From& from)
1832 {
1833 typedef typename component_type<number<To> >::type to_component_type;
1834 typename to_component_type::backend_type to_component;
1835 to_component = from;
1836 eval_set_imag(to, to_component);
1837 }
1838
1839 } // namespace default_ops_adl
1840 namespace default_ops {
1841
1842 template <class To, class From>
eval_set_real(To & to,const From & from)1843 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<To>::value == number_kind_complex>::type eval_set_real(To& to, const From& from)
1844 {
1845 default_ops_adl::eval_set_real_imp(to, from);
1846 }
1847 template <class To, class From>
eval_set_real(To & to,const From & from)1848 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<number_category<To>::value == number_kind_complex>::type eval_set_real(To& to, const From& from)
1849 {
1850 to = from;
1851 }
1852
1853 template <class To, class From>
eval_set_imag(To & to,const From & from)1854 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_imag(To& to, const From& from)
1855 {
1856 default_ops_adl::eval_set_imag_imp(to, from);
1857 }
1858
1859 template <class T>
eval_set_real(T & to,const T & from)1860 inline BOOST_MP_CXX14_CONSTEXPR void eval_set_real(T& to, const T& from)
1861 {
1862 to = from;
1863 }
1864 template <class T>
eval_set_imag(T &,const T &)1865 void BOOST_MP_CXX14_CONSTEXPR eval_set_imag(T&, const T&)
1866 {
1867 BOOST_STATIC_ASSERT_MSG(sizeof(T) == INT_MAX, "eval_set_imag needs to be specialised for each specific backend");
1868 }
1869
1870 //
1871 // These functions are implemented in separate files, but expanded inline here,
1872 // DO NOT CHANGE THE ORDER OF THESE INCLUDES:
1873 //
1874 #include <boost/multiprecision/detail/functions/constants.hpp>
1875 #include <boost/multiprecision/detail/functions/pow.hpp>
1876 #include <boost/multiprecision/detail/functions/trig.hpp>
1877
1878 } // namespace default_ops
1879
1880 //
1881 // Default versions of floating point classification routines:
1882 //
1883 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)1884 inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1885 {
1886 using multiprecision::default_ops::eval_fpclassify;
1887 return eval_fpclassify(arg.backend());
1888 }
1889 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)1890 inline BOOST_MP_CXX14_CONSTEXPR int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1891 {
1892 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1893 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1894 }
1895 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)1896 inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1897 {
1898 int v = fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg);
1899 return (v != (int)FP_INFINITE) && (v != (int)FP_NAN);
1900 }
1901 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)1902 inline BOOST_MP_CXX14_CONSTEXPR bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1903 {
1904 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1905 return isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1906 }
1907 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)1908 inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1909 {
1910 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NAN;
1911 }
1912 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)1913 inline BOOST_MP_CXX14_CONSTEXPR bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1914 {
1915 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1916 return isnan BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1917 }
1918 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)1919 inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1920 {
1921 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_INFINITE;
1922 }
1923 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)1924 inline BOOST_MP_CXX14_CONSTEXPR bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1925 {
1926 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1927 return isinf BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1928 }
1929 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)1930 inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1931 {
1932 return fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(arg) == (int)FP_NORMAL;
1933 }
1934 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)1935 inline BOOST_MP_CXX14_CONSTEXPR bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1936 {
1937 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1938 return isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1939 }
1940
1941 // Default versions of sign manipulation functions, if individual backends can do better than this
1942 // (for example with signed zero), then they should overload these functions further:
1943
1944 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)1945 inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1946 {
1947 return arg.sign();
1948 }
1949 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)1950 inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1951 {
1952 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1953 return sign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1954 }
1955
1956 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)1957 inline BOOST_MP_CXX14_CONSTEXPR int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1958 {
1959 using default_ops::eval_signbit;
1960 return eval_signbit(arg.backend());
1961 }
1962 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)1963 inline BOOST_MP_CXX14_CONSTEXPR int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1964 {
1965 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1966 return signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1967 }
1968 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)1969 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
1970 {
1971 return -arg;
1972 }
1973 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)1974 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
1975 {
1976 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1977 return changesign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
1978 }
1979 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & a,const multiprecision::number<Backend,ExpressionTemplates> & b)1980 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
1981 {
1982 return (boost::multiprecision::signbit)(a) != (boost::multiprecision::signbit)(b) ? (boost::multiprecision::changesign)(a) : a;
1983 }
1984 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & a,const multiprecision::detail::expression<tag,A1,A2,A3,A4> & b)1985 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
1986 {
1987 return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
1988 }
1989 template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & a,const multiprecision::number<Backend,ExpressionTemplates> & b)1990 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
1991 {
1992 return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
1993 }
1994 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & a,const multiprecision::detail::expression<tagb,A1b,A2b,A3b,A4b> & b)1995 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type copysign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
1996 {
1997 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
1998 return copysign BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
1999 }
2000 //
2001 // real and imag:
2002 //
2003 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2004 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
real(const multiprecision::number<Backend,ExpressionTemplates> & a)2005 real(const multiprecision::number<Backend, ExpressionTemplates>& a)
2006 {
2007 using default_ops::eval_real;
2008 typedef typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result_type;
2009 boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
2010 result_type result;
2011 eval_real(result.backend(), a.backend());
2012 return result;
2013 }
2014 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2015 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type
imag(const multiprecision::number<Backend,ExpressionTemplates> & a)2016 imag(const multiprecision::number<Backend, ExpressionTemplates>& a)
2017 {
2018 using default_ops::eval_imag;
2019 typedef typename scalar_result_from_possible_complex<multiprecision::number<Backend, ExpressionTemplates> >::type result_type;
2020 boost::multiprecision::detail::scoped_default_precision<result_type> precision_guard(a);
2021 result_type result;
2022 eval_imag(result.backend(), a.backend());
2023 return result;
2024 }
2025
2026 template <class tag, class A1, class A2, class A3, class A4>
2027 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
real(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2028 real(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2029 {
2030 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2031 detail::scoped_default_precision<value_type> precision_guard(arg);
2032 return real(value_type(arg));
2033 }
2034
2035 template <class tag, class A1, class A2, class A3, class A4>
2036 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
imag(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2037 imag(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2038 {
2039 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2040 detail::scoped_default_precision<value_type> precision_guard(arg);
2041 return imag(value_type(arg));
2042 }
2043
2044 //
2045 // Complex number functions, these are overloaded at the Backend level, we just provide the
2046 // expression template versions here, plus overloads for non-complex types:
2047 //
2048 template <class T, expression_template_option ExpressionTemplates>
2049 inline BOOST_MP_CXX14_CONSTEXPR typename boost::lazy_enable_if_c<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates> > >::type
abs(const number<T,ExpressionTemplates> & v)2050 abs(const number<T, ExpressionTemplates>& v)
2051 {
2052 return BOOST_MP_MOVE(boost::math::hypot(real(v), imag(v)));
2053 }
2054 template <class tag, class A1, class A2, class A3, class A4>
2055 inline BOOST_MP_CXX14_CONSTEXPR typename boost::lazy_enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex, component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type> >::type
abs(const detail::expression<tag,A1,A2,A3,A4> & v)2056 abs(const detail::expression<tag, A1, A2, A3, A4>& v)
2057 {
2058 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2059 return BOOST_MP_MOVE(abs(static_cast<number_type>(v)));
2060 }
2061
2062 template <class T, expression_template_option ExpressionTemplates>
2063 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
arg(const number<T,ExpressionTemplates> & v)2064 arg(const number<T, ExpressionTemplates>& v)
2065 {
2066 return BOOST_MP_MOVE(atan2(imag(v), real(v)));
2067 }
2068 template <class T, expression_template_option ExpressionTemplates>
2069 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
arg(const number<T,ExpressionTemplates> &)2070 arg(const number<T, ExpressionTemplates>&)
2071 {
2072 return 0;
2073 }
2074 template <class tag, class A1, class A2, class A3, class A4>
2075 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex || number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename scalar_result_from_possible_complex<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
arg(const detail::expression<tag,A1,A2,A3,A4> & v)2076 arg(const detail::expression<tag, A1, A2, A3, A4>& v)
2077 {
2078 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2079 return BOOST_MP_MOVE(arg(static_cast<number_type>(v)));
2080 }
2081
2082 template <class T, expression_template_option ExpressionTemplates>
2083 inline BOOST_MP_CXX14_CONSTEXPR typename boost::lazy_enable_if_c<number_category<T>::value == number_kind_complex, component_type<number<T, ExpressionTemplates> > >::type
norm(const number<T,ExpressionTemplates> & v)2084 norm(const number<T, ExpressionTemplates>& v)
2085 {
2086 typename component_type<number<T, ExpressionTemplates> >::type a(real(v)), b(imag(v));
2087 return BOOST_MP_MOVE(a * a + b * b);
2088 }
2089 template <class T, expression_template_option ExpressionTemplates>
2090 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<T>::value != number_kind_complex, typename scalar_result_from_possible_complex<number<T, ExpressionTemplates> >::type>::type
norm(const number<T,ExpressionTemplates> & v)2091 norm(const number<T, ExpressionTemplates>& v)
2092 {
2093 return v * v;
2094 }
2095 template <class tag, class A1, class A2, class A3, class A4>
2096 inline BOOST_MP_CXX14_CONSTEXPR typename scalar_result_from_possible_complex<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
norm(const detail::expression<tag,A1,A2,A3,A4> & v)2097 norm(const detail::expression<tag, A1, A2, A3, A4>& v)
2098 {
2099 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2100 return BOOST_MP_MOVE(norm(static_cast<number_type>(v)));
2101 }
2102
2103 template <class Backend, expression_template_option ExpressionTemplates>
polar(number<Backend,ExpressionTemplates> const & r,number<Backend,ExpressionTemplates> const & theta)2104 BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r, number<Backend, ExpressionTemplates> const& theta)
2105 {
2106 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2107 }
2108
2109 template <class tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
2110 BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
2111 typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
polar(detail::expression<tag,A1,A2,A3,A4> const & r,number<Backend,ExpressionTemplates> const & theta)2112 polar(detail::expression<tag, A1, A2, A3, A4> const& r, number<Backend, ExpressionTemplates> const& theta)
2113 {
2114 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2115 }
2116
2117 template <class Backend, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
2118 BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, ExpressionTemplates> >::value,
2119 typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
polar(number<Backend,ExpressionTemplates> const & r,detail::expression<tag,A1,A2,A3,A4> const & theta)2120 polar(number<Backend, ExpressionTemplates> const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
2121 {
2122 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2123 }
2124
2125 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
2126 BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_same<typename detail::expression<tag, A1, A2, A3, A4>::result_type, typename detail::expression<tagb, A1b, A2b, A3b, A4b>::result_type>::value,
2127 typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
polar(detail::expression<tag,A1,A2,A3,A4> const & r,detail::expression<tagb,A1b,A2b,A3b,A4b> const & theta)2128 polar(detail::expression<tag, A1, A2, A3, A4> const& r, detail::expression<tagb, A1b, A2b, A3b, A4b> const& theta)
2129 {
2130 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type scalar_type;
2131 return typename complex_result_from_scalar<scalar_type>::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta)));
2132 }
2133 //
2134 // We also allow the first argument to polar to be an arithmetic type (probably a literal):
2135 //
2136 template <class Scalar, class Backend, expression_template_option ExpressionTemplates>
2137 BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<boost::is_arithmetic<Scalar>::value, typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type>::type
polar(Scalar const & r,number<Backend,ExpressionTemplates> const & theta)2138 polar(Scalar const& r, number<Backend, ExpressionTemplates> const& theta)
2139 {
2140 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(number<Backend, ExpressionTemplates>(r * cos(theta)), number<Backend, ExpressionTemplates>(r * sin(theta)));
2141 }
2142
2143 template <class tag, class A1, class A2, class A3, class A4, class Scalar>
2144 BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<boost::is_arithmetic<Scalar>::value,
2145 typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type>::type
polar(Scalar const & r,detail::expression<tag,A1,A2,A3,A4> const & theta)2146 polar(Scalar const& r, detail::expression<tag, A1, A2, A3, A4> const& theta)
2147 {
2148 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type scalar_type;
2149 return typename complex_result_from_scalar<scalar_type>::type(scalar_type(r * cos(theta)), scalar_type(r * sin(theta)));
2150 }
2151 //
2152 // Single argument overloads:
2153 //
2154 template <class Backend, expression_template_option ExpressionTemplates>
polar(number<Backend,ExpressionTemplates> const & r)2155 BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type polar(number<Backend, ExpressionTemplates> const& r)
2156 {
2157 return typename complex_result_from_scalar<number<Backend, ExpressionTemplates> >::type(r);
2158 }
2159
2160 template <class tag, class A1, class A2, class A3, class A4>
2161 BOOST_MP_CXX14_CONSTEXPR typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
polar(detail::expression<tag,A1,A2,A3,A4> const & r)2162 polar(detail::expression<tag, A1, A2, A3, A4> const& r)
2163 {
2164 return typename complex_result_from_scalar<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type(r);
2165 }
2166
2167 } // namespace multiprecision
2168
2169 namespace math {
2170
2171 //
2172 // Import Math functions here, so they can be found by Boost.Math:
2173 //
2174 using boost::multiprecision::changesign;
2175 using boost::multiprecision::copysign;
2176 using boost::multiprecision::fpclassify;
2177 using boost::multiprecision::isfinite;
2178 using boost::multiprecision::isinf;
2179 using boost::multiprecision::isnan;
2180 using boost::multiprecision::isnormal;
2181 using boost::multiprecision::sign;
2182 using boost::multiprecision::signbit;
2183
2184 } // namespace math
2185
2186 namespace multiprecision {
2187
2188 typedef ::boost::math::policies::policy<
2189 ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>,
2190 ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>,
2191 ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>,
2192 ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>,
2193 ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error> >
2194 c99_error_policy;
2195
2196 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2197 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2198 asinh
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2199 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2200 {
2201 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2202 return boost::math::asinh(arg, c99_error_policy());
2203 }
2204 template <class tag, class A1, class A2, class A3, class A4>
2205 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2206 asinh
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2207 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2208 {
2209 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2210 detail::scoped_default_precision<value_type> precision_guard(arg);
2211 return asinh(value_type(arg));
2212 }
2213 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2214 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2215 acosh
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2216 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2217 {
2218 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2219 return boost::math::acosh(arg, c99_error_policy());
2220 }
2221 template <class tag, class A1, class A2, class A3, class A4>
2222 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2223 acosh
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2224 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2225 {
2226 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2227 detail::scoped_default_precision<value_type> precision_guard(arg);
2228 return acosh(value_type(arg));
2229 }
2230 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
2231 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value != number_kind_complex, multiprecision::number<Backend, ExpressionTemplates> >::type
2232 atanh
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2233 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2234 {
2235 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2236 return boost::math::atanh(arg, c99_error_policy());
2237 }
2238 template <class tag, class A1, class A2, class A3, class A4>
2239 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<number_category<typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type>::type
2240 atanh
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2241 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2242 {
2243 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2244 detail::scoped_default_precision<value_type> precision_guard(arg);
2245 return atanh(value_type(arg));
2246 }
2247 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2248 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2249 {
2250 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2251 return boost::math::cbrt(arg, c99_error_policy());
2252 }
2253 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2254 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type cbrt BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2255 {
2256 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2257 detail::scoped_default_precision<value_type> precision_guard(arg);
2258 return cbrt(value_type(arg));
2259 }
2260 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2261 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2262 {
2263 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2264 return boost::math::erf(arg, c99_error_policy());
2265 }
2266 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2267 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2268 {
2269 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2270 detail::scoped_default_precision<value_type> precision_guard(arg);
2271 return erf(value_type(arg));
2272 }
2273 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2274 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2275 {
2276 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2277 return boost::math::erfc(arg, c99_error_policy());
2278 }
2279 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2280 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type erfc BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2281 {
2282 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2283 detail::scoped_default_precision<value_type> precision_guard(arg);
2284 return erfc(value_type(arg));
2285 }
2286 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2287 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2288 {
2289 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2290 return boost::math::expm1(arg, c99_error_policy());
2291 }
2292 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2293 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type expm1 BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2294 {
2295 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2296 detail::scoped_default_precision<value_type> precision_guard(arg);
2297 return expm1(value_type(arg));
2298 }
2299 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2300 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2301 {
2302 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2303 multiprecision::number<Backend, ExpressionTemplates> result;
2304 result = boost::math::lgamma(arg, c99_error_policy());
2305 if ((boost::multiprecision::isnan)(result) && !(boost::multiprecision::isnan)(arg))
2306 {
2307 result = std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::infinity();
2308 errno = ERANGE;
2309 }
2310 return result;
2311 }
2312 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2313 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type lgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2314 {
2315 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2316 detail::scoped_default_precision<value_type> precision_guard(arg);
2317 return lgamma(value_type(arg));
2318 }
2319 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2320 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2321 {
2322 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2323 if ((arg == 0) && std::numeric_limits<multiprecision::number<Backend, ExpressionTemplates> >::has_infinity)
2324 {
2325 errno = ERANGE;
2326 return 1 / arg;
2327 }
2328 return boost::math::tgamma(arg, c99_error_policy());
2329 }
2330 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2331 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type tgamma BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2332 {
2333 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2334 detail::scoped_default_precision<value_type> precision_guard(arg);
2335 return tgamma(value_type(arg));
2336 }
2337
2338 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2339 inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2340 {
2341 return lround(arg);
2342 }
2343 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2344 inline BOOST_MP_CXX14_CONSTEXPR long lrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2345 {
2346 return lround(arg);
2347 }
2348 #ifndef BOOST_NO_LONG_LONG
2349 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2350 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2351 {
2352 return llround(arg);
2353 }
2354 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2355 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llrint BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2356 {
2357 return llround(arg);
2358 }
2359 #endif
2360 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & arg)2361 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
2362 {
2363 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(arg);
2364 return boost::math::log1p(arg, c99_error_policy());
2365 }
2366 template <class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & arg)2367 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type log1p BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
2368 {
2369 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2370 detail::scoped_default_precision<value_type> precision_guard(arg);
2371 return log1p(value_type(arg));
2372 }
2373
2374 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & a,const multiprecision::number<Backend,ExpressionTemplates> & b)2375 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2376 {
2377 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2378 return boost::math::nextafter(a, b, c99_error_policy());
2379 }
2380 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & a,const multiprecision::detail::expression<tag,A1,A2,A3,A4> & b)2381 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
2382 {
2383 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2384 return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
2385 }
2386 template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & a,const multiprecision::number<Backend,ExpressionTemplates> & b)2387 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2388 {
2389 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2390 return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
2391 }
2392 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & a,const multiprecision::detail::expression<tagb,A1b,A2b,A3b,A4b> & b)2393 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
2394 {
2395 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2396 detail::scoped_default_precision<value_type> precision_guard(a, b);
2397 return nextafter BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
2398 }
2399 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & a,const multiprecision::number<Backend,ExpressionTemplates> & b)2400 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2401 {
2402 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2403 return boost::math::nextafter(a, b, c99_error_policy());
2404 }
2405 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend,ExpressionTemplates> & a,const multiprecision::detail::expression<tag,A1,A2,A3,A4> & b)2406 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& a, const multiprecision::detail::expression<tag, A1, A2, A3, A4>& b)
2407 {
2408 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2409 return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(a, multiprecision::number<Backend, ExpressionTemplates>(b));
2410 }
2411 template <class tag, class A1, class A2, class A3, class A4, class Backend, multiprecision::expression_template_option ExpressionTemplates>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & a,const multiprecision::number<Backend,ExpressionTemplates> & b)2412 inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::number<Backend, ExpressionTemplates>& b)
2413 {
2414 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(a, b);
2415 return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(multiprecision::number<Backend, ExpressionTemplates>(a), b);
2416 }
2417 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b>
BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag,A1,A2,A3,A4> & a,const multiprecision::detail::expression<tagb,A1b,A2b,A3b,A4b> & b)2418 inline BOOST_MP_CXX14_CONSTEXPR typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& a, const multiprecision::detail::expression<tagb, A1b, A2b, A3b, A4b>& b)
2419 {
2420 typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
2421 detail::scoped_default_precision<value_type> precision_guard(a, b);
2422 return nexttoward BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(a), value_type(b));
2423 }
2424
2425 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
add(number<B1,ET1> & result,const number<B2,ET2> & a,const number<B3,ET3> & b)2426 inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2427 {
2428 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2429 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2430 using default_ops::eval_add;
2431 eval_add(result.backend(), a.backend(), b.backend());
2432 return result;
2433 }
2434
2435 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
subtract(number<B1,ET1> & result,const number<B2,ET2> & a,const number<B3,ET3> & b)2436 inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2437 {
2438 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2439 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2440 using default_ops::eval_subtract;
2441 eval_subtract(result.backend(), a.backend(), b.backend());
2442 return result;
2443 }
2444
2445 template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
multiply(number<B1,ET1> & result,const number<B2,ET2> & a,const number<B3,ET3> & b)2446 inline BOOST_MP_CXX14_CONSTEXPR number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
2447 {
2448 BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
2449 BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
2450 using default_ops::eval_multiply;
2451 eval_multiply(result.backend(), a.backend(), b.backend());
2452 return result;
2453 }
2454
2455 template <class B, expression_template_option ET, class I>
2456 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
add(number<B,ET> & result,const I & a,const I & b)2457 add(number<B, ET>& result, const I& a, const I& b)
2458 {
2459 using default_ops::eval_add;
2460 typedef typename detail::canonical<I, B>::type canonical_type;
2461 eval_add(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2462 return result;
2463 }
2464
2465 template <class B, expression_template_option ET, class I>
2466 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
subtract(number<B,ET> & result,const I & a,const I & b)2467 subtract(number<B, ET>& result, const I& a, const I& b)
2468 {
2469 using default_ops::eval_subtract;
2470 typedef typename detail::canonical<I, B>::type canonical_type;
2471 eval_subtract(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2472 return result;
2473 }
2474
2475 template <class B, expression_template_option ET, class I>
2476 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
multiply(number<B,ET> & result,const I & a,const I & b)2477 multiply(number<B, ET>& result, const I& a, const I& b)
2478 {
2479 using default_ops::eval_multiply;
2480 typedef typename detail::canonical<I, B>::type canonical_type;
2481 eval_multiply(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
2482 return result;
2483 }
2484
2485 template <class tag, class A1, class A2, class A3, class A4, class Policy>
trunc(const detail::expression<tag,A1,A2,A3,A4> & v,const Policy & pol)2486 inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<tag, A1, A2, A3, A4>::result_type trunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2487 {
2488 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2489 return BOOST_MP_MOVE(trunc(number_type(v), pol));
2490 }
2491
2492 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
trunc(const number<Backend,ExpressionTemplates> & v,const Policy &)2493 inline BOOST_MP_CXX14_CONSTEXPR number<Backend, ExpressionTemplates> trunc(const number<Backend, ExpressionTemplates>& v, const Policy&)
2494 {
2495 using default_ops::eval_trunc;
2496 detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(v);
2497 number<Backend, ExpressionTemplates> result;
2498 eval_trunc(result.backend(), v.backend());
2499 return result;
2500 }
2501
2502 template <class tag, class A1, class A2, class A3, class A4, class Policy>
itrunc(const detail::expression<tag,A1,A2,A3,A4> & v,const Policy & pol)2503 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2504 {
2505 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2506 number_type r(trunc(v, pol));
2507 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
2508 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, number_type(v), 0, pol);
2509 return r.template convert_to<int>();
2510 }
2511 template <class tag, class A1, class A2, class A3, class A4>
itrunc(const detail::expression<tag,A1,A2,A3,A4> & v)2512 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2513 {
2514 return itrunc(v, boost::math::policies::policy<>());
2515 }
2516 template <class Backend, expression_template_option ExpressionTemplates, class Policy>
itrunc(const number<Backend,ExpressionTemplates> & v,const Policy & pol)2517 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v, const Policy& pol)
2518 {
2519 number<Backend, ExpressionTemplates> r(trunc(v, pol));
2520 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
2521 return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol);
2522 return r.template convert_to<int>();
2523 }
2524 template <class Backend, expression_template_option ExpressionTemplates>
itrunc(const number<Backend,ExpressionTemplates> & v)2525 inline BOOST_MP_CXX14_CONSTEXPR int itrunc(const number<Backend, ExpressionTemplates>& v)
2526 {
2527 return itrunc(v, boost::math::policies::policy<>());
2528 }
2529 template <class tag, class A1, class A2, class A3, class A4, class Policy>
ltrunc(const detail::expression<tag,A1,A2,A3,A4> & v,const Policy & pol)2530 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2531 {
2532 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2533 number_type r(trunc(v, pol));
2534 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
2535 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, number_type(v), 0L, pol);
2536 return r.template convert_to<long>();
2537 }
2538 template <class tag, class A1, class A2, class A3, class A4>
ltrunc(const detail::expression<tag,A1,A2,A3,A4> & v)2539 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2540 {
2541 return ltrunc(v, boost::math::policies::policy<>());
2542 }
2543 template <class T, expression_template_option ExpressionTemplates, class Policy>
ltrunc(const number<T,ExpressionTemplates> & v,const Policy & pol)2544 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
2545 {
2546 number<T, ExpressionTemplates> r(trunc(v, pol));
2547 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
2548 return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol);
2549 return r.template convert_to<long>();
2550 }
2551 template <class T, expression_template_option ExpressionTemplates>
ltrunc(const number<T,ExpressionTemplates> & v)2552 inline BOOST_MP_CXX14_CONSTEXPR long ltrunc(const number<T, ExpressionTemplates>& v)
2553 {
2554 return ltrunc(v, boost::math::policies::policy<>());
2555 }
2556 #ifndef BOOST_NO_LONG_LONG
2557 template <class tag, class A1, class A2, class A3, class A4, class Policy>
lltrunc(const detail::expression<tag,A1,A2,A3,A4> & v,const Policy & pol)2558 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2559 {
2560 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2561 number_type r(trunc(v, pol));
2562 if ((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
2563 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, pol);
2564 return r.template convert_to<boost::long_long_type>();
2565 }
2566 template <class tag, class A1, class A2, class A3, class A4>
lltrunc(const detail::expression<tag,A1,A2,A3,A4> & v)2567 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
2568 {
2569 return lltrunc(v, boost::math::policies::policy<>());
2570 }
2571 template <class T, expression_template_option ExpressionTemplates, class Policy>
lltrunc(const number<T,ExpressionTemplates> & v,const Policy & pol)2572 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
2573 {
2574 number<T, ExpressionTemplates> r(trunc(v, pol));
2575 if ((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
2576 return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol);
2577 return r.template convert_to<boost::long_long_type>();
2578 }
2579 template <class T, expression_template_option ExpressionTemplates>
lltrunc(const number<T,ExpressionTemplates> & v)2580 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type lltrunc(const number<T, ExpressionTemplates>& v)
2581 {
2582 return lltrunc(v, boost::math::policies::policy<>());
2583 }
2584 #endif
2585 template <class tag, class A1, class A2, class A3, class A4, class Policy>
round(const detail::expression<tag,A1,A2,A3,A4> & v,const Policy & pol)2586 inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<tag, A1, A2, A3, A4>::result_type round(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2587 {
2588 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2589 return BOOST_MP_MOVE(round(static_cast<number_type>(v), pol));
2590 }
2591 template <class T, expression_template_option ExpressionTemplates, class Policy>
round(const number<T,ExpressionTemplates> & v,const Policy &)2592 inline BOOST_MP_CXX14_CONSTEXPR number<T, ExpressionTemplates> round(const number<T, ExpressionTemplates>& v, const Policy&)
2593 {
2594 using default_ops::eval_round;
2595 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2596 number<T, ExpressionTemplates> result;
2597 eval_round(result.backend(), v.backend());
2598 return result;
2599 }
2600
2601 template <class tag, class A1, class A2, class A3, class A4, class Policy>
iround(const detail::expression<tag,A1,A2,A3,A4> & v,const Policy & pol)2602 inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2603 {
2604 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2605 number_type r(round(v, pol));
2606 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
2607 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0, pol);
2608 return r.template convert_to<int>();
2609 }
2610 template <class tag, class A1, class A2, class A3, class A4>
iround(const detail::expression<tag,A1,A2,A3,A4> & v)2611 inline BOOST_MP_CXX14_CONSTEXPR int iround(const detail::expression<tag, A1, A2, A3, A4>& v)
2612 {
2613 return iround(v, boost::math::policies::policy<>());
2614 }
2615 template <class T, expression_template_option ExpressionTemplates, class Policy>
iround(const number<T,ExpressionTemplates> & v,const Policy & pol)2616 inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v, const Policy& pol)
2617 {
2618 number<T, ExpressionTemplates> r(round(v, pol));
2619 if ((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
2620 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol);
2621 return r.template convert_to<int>();
2622 }
2623 template <class T, expression_template_option ExpressionTemplates>
iround(const number<T,ExpressionTemplates> & v)2624 inline BOOST_MP_CXX14_CONSTEXPR int iround(const number<T, ExpressionTemplates>& v)
2625 {
2626 return iround(v, boost::math::policies::policy<>());
2627 }
2628 template <class tag, class A1, class A2, class A3, class A4, class Policy>
lround(const detail::expression<tag,A1,A2,A3,A4> & v,const Policy & pol)2629 inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2630 {
2631 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2632 number_type r(round(v, pol));
2633 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
2634 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, number_type(v), 0L, pol);
2635 return r.template convert_to<long>();
2636 }
2637 template <class tag, class A1, class A2, class A3, class A4>
lround(const detail::expression<tag,A1,A2,A3,A4> & v)2638 inline BOOST_MP_CXX14_CONSTEXPR long lround(const detail::expression<tag, A1, A2, A3, A4>& v)
2639 {
2640 return lround(v, boost::math::policies::policy<>());
2641 }
2642 template <class T, expression_template_option ExpressionTemplates, class Policy>
lround(const number<T,ExpressionTemplates> & v,const Policy & pol)2643 inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v, const Policy& pol)
2644 {
2645 number<T, ExpressionTemplates> r(round(v, pol));
2646 if ((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
2647 return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol);
2648 return r.template convert_to<long>();
2649 }
2650 template <class T, expression_template_option ExpressionTemplates>
lround(const number<T,ExpressionTemplates> & v)2651 inline BOOST_MP_CXX14_CONSTEXPR long lround(const number<T, ExpressionTemplates>& v)
2652 {
2653 return lround(v, boost::math::policies::policy<>());
2654 }
2655 #ifndef BOOST_NO_LONG_LONG
2656 template <class tag, class A1, class A2, class A3, class A4, class Policy>
llround(const detail::expression<tag,A1,A2,A3,A4> & v,const Policy & pol)2657 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
2658 {
2659 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2660 number_type r(round(v, pol));
2661 if ((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
2662 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol);
2663 return r.template convert_to<boost::long_long_type>();
2664 }
2665 template <class tag, class A1, class A2, class A3, class A4>
llround(const detail::expression<tag,A1,A2,A3,A4> & v)2666 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llround(const detail::expression<tag, A1, A2, A3, A4>& v)
2667 {
2668 return llround(v, boost::math::policies::policy<>());
2669 }
2670 template <class T, expression_template_option ExpressionTemplates, class Policy>
llround(const number<T,ExpressionTemplates> & v,const Policy & pol)2671 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
2672 {
2673 number<T, ExpressionTemplates> r(round(v, pol));
2674 if ((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
2675 return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol);
2676 return r.template convert_to<boost::long_long_type>();
2677 }
2678 template <class T, expression_template_option ExpressionTemplates>
llround(const number<T,ExpressionTemplates> & v)2679 inline BOOST_MP_CXX14_CONSTEXPR boost::long_long_type llround(const number<T, ExpressionTemplates>& v)
2680 {
2681 return llround(v, boost::math::policies::policy<>());
2682 }
2683 #endif
2684 //
2685 // frexp does not return an expression template since we require the
2686 // integer argument to be evaluated even if the returned value is
2687 // not assigned to anything...
2688 //
2689 template <class T, expression_template_option ExpressionTemplates>
frexp(const number<T,ExpressionTemplates> & v,short * pint)2690 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, short* pint)
2691 {
2692 using default_ops::eval_frexp;
2693 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2694 number<T, ExpressionTemplates> result;
2695 eval_frexp(result.backend(), v.backend(), pint);
2696 return result;
2697 }
2698 template <class tag, class A1, class A2, class A3, class A4>
2699 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
frexp(const detail::expression<tag,A1,A2,A3,A4> & v,short * pint)2700 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, short* pint)
2701 {
2702 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2703 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
2704 }
2705 template <class T, expression_template_option ExpressionTemplates>
frexp(const number<T,ExpressionTemplates> & v,int * pint)2706 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, int* pint)
2707 {
2708 using default_ops::eval_frexp;
2709 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2710 number<T, ExpressionTemplates> result;
2711 eval_frexp(result.backend(), v.backend(), pint);
2712 return result;
2713 }
2714 template <class tag, class A1, class A2, class A3, class A4>
2715 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
frexp(const detail::expression<tag,A1,A2,A3,A4> & v,int * pint)2716 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, int* pint)
2717 {
2718 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2719 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
2720 }
2721 template <class T, expression_template_option ExpressionTemplates>
frexp(const number<T,ExpressionTemplates> & v,long * pint)2722 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long* pint)
2723 {
2724 using default_ops::eval_frexp;
2725 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2726 number<T, ExpressionTemplates> result;
2727 eval_frexp(result.backend(), v.backend(), pint);
2728 return result;
2729 }
2730 template <class tag, class A1, class A2, class A3, class A4>
2731 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
frexp(const detail::expression<tag,A1,A2,A3,A4> & v,long * pint)2732 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long* pint)
2733 {
2734 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2735 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
2736 }
2737 template <class T, expression_template_option ExpressionTemplates>
frexp(const number<T,ExpressionTemplates> & v,boost::long_long_type * pint)2738 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, boost::long_long_type* pint)
2739 {
2740 using default_ops::eval_frexp;
2741 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2742 number<T, ExpressionTemplates> result;
2743 eval_frexp(result.backend(), v.backend(), pint);
2744 return result;
2745 }
2746 template <class tag, class A1, class A2, class A3, class A4>
2747 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
frexp(const detail::expression<tag,A1,A2,A3,A4> & v,boost::long_long_type * pint)2748 frexp(const detail::expression<tag, A1, A2, A3, A4>& v, boost::long_long_type* pint)
2749 {
2750 typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
2751 return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
2752 }
2753 //
2754 // modf does not return an expression template since we require the
2755 // second argument to be evaluated even if the returned value is
2756 // not assigned to anything...
2757 //
2758 template <class T, expression_template_option ExpressionTemplates>
modf(const number<T,ExpressionTemplates> & v,number<T,ExpressionTemplates> * pipart)2759 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const number<T, ExpressionTemplates>& v, number<T, ExpressionTemplates>* pipart)
2760 {
2761 using default_ops::eval_modf;
2762 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2763 number<T, ExpressionTemplates> result;
2764 eval_modf(result.backend(), v.backend(), pipart ? &pipart->backend() : 0);
2765 return result;
2766 }
2767 template <class T, expression_template_option ExpressionTemplates, class tag, class A1, class A2, class A3, class A4>
modf(const detail::expression<tag,A1,A2,A3,A4> & v,number<T,ExpressionTemplates> * pipart)2768 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type modf(const detail::expression<tag, A1, A2, A3, A4>& v, number<T, ExpressionTemplates>* pipart)
2769 {
2770 using default_ops::eval_modf;
2771 detail::scoped_default_precision<multiprecision::number<T, ExpressionTemplates> > precision_guard(v);
2772 number<T, ExpressionTemplates> result, arg(v);
2773 eval_modf(result.backend(), arg.backend(), pipart ? &pipart->backend() : 0);
2774 return result;
2775 }
2776
2777 //
2778 // Integer square root:
2779 //
2780 template <class B, expression_template_option ExpressionTemplates>
2781 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
sqrt(const number<B,ExpressionTemplates> & x)2782 sqrt(const number<B, ExpressionTemplates>& x)
2783 {
2784 using default_ops::eval_integer_sqrt;
2785 number<B, ExpressionTemplates> s, r;
2786 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
2787 return s;
2788 }
2789 //
2790 // fma:
2791 //
2792
2793 namespace default_ops {
2794
2795 struct fma_func
2796 {
2797 template <class B, class T, class U, class V>
operator ()boost::multiprecision::default_ops::fma_func2798 BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, const V& c) const
2799 {
2800 eval_multiply_add(result, a, b, c);
2801 }
2802 };
2803
2804 } // namespace default_ops
2805
2806 template <class Backend, class U, class V>
2807 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2808 mpl::and_<
2809 mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
2810 mpl::or_<
2811 is_number<U>,
2812 is_number_expression<U>,
2813 is_arithmetic<U> >,
2814 mpl::or_<
2815 is_number<V>,
2816 is_number_expression<V>,
2817 is_arithmetic<V> > >,
2818 detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V> >::type
fma(const number<Backend,et_on> & a,const U & b,const V & c)2819 fma(const number<Backend, et_on>& a, const U& b, const V& c)
2820 {
2821 return detail::expression<detail::function, default_ops::fma_func, number<Backend, et_on>, U, V>(
2822 default_ops::fma_func(), a, b, c);
2823 }
2824
2825 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U, class V>
2826 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2827 mpl::and_<
2828 mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point>,
2829 mpl::or_<
2830 is_number<U>,
2831 is_number_expression<U>,
2832 is_arithmetic<U> >,
2833 mpl::or_<
2834 is_number<V>,
2835 is_number_expression<V>,
2836 is_arithmetic<V> > >,
2837 detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V> >::type
fma(const detail::expression<tag,Arg1,Arg2,Arg3,Arg4> & a,const U & b,const V & c)2838 fma(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, const V& c)
2839 {
2840 return detail::expression<detail::function, default_ops::fma_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, V>(
2841 default_ops::fma_func(), a, b, c);
2842 }
2843
2844 template <class Backend, class U, class V>
2845 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2846 mpl::and_<
2847 mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
2848 mpl::or_<
2849 is_number<U>,
2850 is_number_expression<U>,
2851 is_arithmetic<U> >,
2852 mpl::or_<
2853 is_number<V>,
2854 is_number_expression<V>,
2855 is_arithmetic<V> > >,
2856 number<Backend, et_off> >::type
fma(const number<Backend,et_off> & a,const U & b,const V & c)2857 fma(const number<Backend, et_off>& a, const U& b, const V& c)
2858 {
2859 using default_ops::eval_multiply_add;
2860 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
2861 number<Backend, et_off> result;
2862 eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
2863 return result;
2864 }
2865
2866 template <class U, class Backend, class V>
2867 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2868 mpl::and_<
2869 mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
2870 is_arithmetic<U>,
2871 mpl::or_<
2872 is_number<V>,
2873 is_number_expression<V>,
2874 is_arithmetic<V> > >,
2875 detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V> >::type
fma(const U & a,const number<Backend,et_on> & b,const V & c)2876 fma(const U& a, const number<Backend, et_on>& b, const V& c)
2877 {
2878 return detail::expression<detail::function, default_ops::fma_func, U, number<Backend, et_on>, V>(
2879 default_ops::fma_func(), a, b, c);
2880 }
2881
2882 template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4, class V>
2883 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2884 mpl::and_<
2885 mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point>,
2886 is_arithmetic<U>,
2887 mpl::or_<
2888 is_number<V>,
2889 is_number_expression<V>,
2890 is_arithmetic<V> > >,
2891 detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V> >::type
fma(const U & a,const detail::expression<tag,Arg1,Arg2,Arg3,Arg4> & b,const V & c)2892 fma(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, const V& c)
2893 {
2894 return detail::expression<detail::function, default_ops::fma_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, V>(
2895 default_ops::fma_func(), a, b, c);
2896 }
2897
2898 template <class U, class Backend, class V>
2899 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2900 mpl::and_<
2901 mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
2902 is_arithmetic<U>,
2903 mpl::or_<
2904 is_number<V>,
2905 is_number_expression<V>,
2906 is_arithmetic<V> > >,
2907 number<Backend, et_off> >::type
fma(const U & a,const number<Backend,et_off> & b,const V & c)2908 fma(const U& a, const number<Backend, et_off>& b, const V& c)
2909 {
2910 using default_ops::eval_multiply_add;
2911 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
2912 number<Backend, et_off> result;
2913 eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
2914 return result;
2915 }
2916
2917 template <class U, class V, class Backend>
2918 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2919 mpl::and_<
2920 mpl::bool_<number_category<number<Backend, et_on> >::value == number_kind_floating_point>,
2921 is_arithmetic<U>,
2922 is_arithmetic<V> >,
2923 detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> > >::type
fma(const U & a,const V & b,const number<Backend,et_on> & c)2924 fma(const U& a, const V& b, const number<Backend, et_on>& c)
2925 {
2926 return detail::expression<detail::function, default_ops::fma_func, U, V, number<Backend, et_on> >(
2927 default_ops::fma_func(), a, b, c);
2928 }
2929
2930 template <class U, class V, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
2931 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2932 mpl::and_<
2933 mpl::bool_<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point>,
2934 is_arithmetic<U>,
2935 is_arithmetic<V> >,
2936 detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > >::type
fma(const U & a,const V & b,const detail::expression<tag,Arg1,Arg2,Arg3,Arg4> & c)2937 fma(const U& a, const V& b, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& c)
2938 {
2939 return detail::expression<detail::function, default_ops::fma_func, U, V, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(
2940 default_ops::fma_func(), a, b, c);
2941 }
2942
2943 template <class U, class V, class Backend>
2944 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if<
2945 mpl::and_<
2946 mpl::bool_<number_category<number<Backend, et_off> >::value == number_kind_floating_point>,
2947 is_arithmetic<U>,
2948 is_arithmetic<V> >,
2949 number<Backend, et_off> >::type
fma(const U & a,const V & b,const number<Backend,et_off> & c)2950 fma(const U& a, const V& b, const number<Backend, et_off>& c)
2951 {
2952 using default_ops::eval_multiply_add;
2953 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b, c);
2954 number<Backend, et_off> result;
2955 eval_multiply_add(result.backend(), number<Backend, et_off>::canonical_value(a), number<Backend, et_off>::canonical_value(b), number<Backend, et_off>::canonical_value(c));
2956 return result;
2957 }
2958
2959 namespace default_ops {
2960
2961 struct remquo_func
2962 {
2963 template <class B, class T, class U>
operator ()boost::multiprecision::default_ops::remquo_func2964 BOOST_MP_CXX14_CONSTEXPR void operator()(B& result, const T& a, const U& b, int* pi) const
2965 {
2966 eval_remquo(result, a, b, pi);
2967 }
2968 };
2969
2970 } // namespace default_ops
2971
2972 template <class Backend, class U>
2973 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
2974 number_category<number<Backend, et_on> >::value == number_kind_floating_point,
2975 detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*> >::type
remquo(const number<Backend,et_on> & a,const U & b,int * pi)2976 remquo(const number<Backend, et_on>& a, const U& b, int* pi)
2977 {
2978 return detail::expression<detail::function, default_ops::remquo_func, number<Backend, et_on>, U, int*>(
2979 default_ops::remquo_func(), a, b, pi);
2980 }
2981
2982 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class U>
2983 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
2984 number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point,
2985 detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*> >::type
remquo(const detail::expression<tag,Arg1,Arg2,Arg3,Arg4> & a,const U & b,int * pi)2986 remquo(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const U& b, int* pi)
2987 {
2988 return detail::expression<detail::function, default_ops::remquo_func, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, U, int*>(
2989 default_ops::remquo_func(), a, b, pi);
2990 }
2991
2992 template <class U, class Backend>
2993 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
2994 (number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
2995 detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*> >::type
remquo(const U & a,const number<Backend,et_on> & b,int * pi)2996 remquo(const U& a, const number<Backend, et_on>& b, int* pi)
2997 {
2998 return detail::expression<detail::function, default_ops::remquo_func, U, number<Backend, et_on>, int*>(
2999 default_ops::remquo_func(), a, b, pi);
3000 }
3001
3002 template <class U, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
3003 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
3004 (number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
3005 detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*> >::type
remquo(const U & a,const detail::expression<tag,Arg1,Arg2,Arg3,Arg4> & b,int * pi)3006 remquo(const U& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b, int* pi)
3007 {
3008 return detail::expression<detail::function, default_ops::remquo_func, U, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, int*>(
3009 default_ops::remquo_func(), a, b, pi);
3010 }
3011
3012 template <class Backend, class U>
3013 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
3014 number_category<number<Backend, et_on> >::value == number_kind_floating_point,
3015 number<Backend, et_off> >::type
remquo(const number<Backend,et_off> & a,const U & b,int * pi)3016 remquo(const number<Backend, et_off>& a, const U& b, int* pi)
3017 {
3018 using default_ops::eval_remquo;
3019 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
3020 number<Backend, et_off> result;
3021 eval_remquo(result.backend(), a.backend(), number<Backend, et_off>::canonical_value(b), pi);
3022 return result;
3023 }
3024 template <class U, class Backend>
3025 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<
3026 (number_category<number<Backend, et_on> >::value == number_kind_floating_point) && !is_number<U>::value && !is_number_expression<U>::value,
3027 number<Backend, et_off> >::type
remquo(const U & a,const number<Backend,et_off> & b,int * pi)3028 remquo(const U& a, const number<Backend, et_off>& b, int* pi)
3029 {
3030 using default_ops::eval_remquo;
3031 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(a, b);
3032 number<Backend, et_off> result;
3033 eval_remquo(result.backend(), number<Backend, et_off>::canonical_value(a), b.backend(), pi);
3034 return result;
3035 }
3036
3037 template <class B, expression_template_option ExpressionTemplates>
3038 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
sqrt(const number<B,ExpressionTemplates> & x,number<B,ExpressionTemplates> & r)3039 sqrt(const number<B, ExpressionTemplates>& x, number<B, ExpressionTemplates>& r)
3040 {
3041 using default_ops::eval_integer_sqrt;
3042 detail::scoped_default_precision<multiprecision::number<B, ExpressionTemplates> > precision_guard(x, r);
3043 number<B, ExpressionTemplates> s;
3044 eval_integer_sqrt(s.backend(), r.backend(), x.backend());
3045 return s;
3046 }
3047
3048 // clang-format off
3049
3050 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
3051 #define UNARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
3052 template <class Backend> \
3053 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<Backend>::value == category, number<Backend, et_on> > ::type \
3054 func(number<Backend, et_on>&& arg) \
3055 { \
3056 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3057 number<Backend, et_off> result; \
3058 using default_ops::BOOST_JOIN(eval_, func); \
3059 BOOST_JOIN(eval_, func)(result.backend(), arg.backend()); \
3060 return result; \
3061 } \
3062
3063 #define BINARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
3064 template <class Backend> \
3065 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<Backend>::value == category, number<Backend, et_on> >::type func(number<Backend, et_on>&& arg, const number<Backend, et_on>& a) \
3066 { \
3067 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
3068 number<Backend, et_off> result; \
3069 using default_ops::BOOST_JOIN(eval_, func); \
3070 BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3071 return result; \
3072 } \
3073 template <class Backend> \
3074 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<Backend>::value == category, number<Backend, et_on> >::type func(const number<Backend, et_on>& arg, number<Backend, et_on>&& a) \
3075 { \
3076 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
3077 number<Backend, et_off> result; \
3078 using default_ops::BOOST_JOIN(eval_, func); \
3079 BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3080 return result; \
3081 } \
3082 template <class Backend> \
3083 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<Backend>::value == category, number<Backend, et_on> >::type func(number<Backend, et_on>&& arg, number<Backend, et_on>&& a) \
3084 { \
3085 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
3086 number<Backend, et_off> result; \
3087 using default_ops::BOOST_JOIN(eval_, func); \
3088 BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3089 return result; \
3090 } \
3091 template <class Backend, class tag, class A1, class A2, class A3, class A4> \
3092 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(number_category<Backend>::value == category) && (boost::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3093 number<Backend, et_on> > ::type \
3094 func(number<Backend, et_on>&& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
3095 { \
3096 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3097 number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3098 } \
3099 template <class tag, class A1, class A2, class A3, class A4, class Backend> \
3100 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(number_category<Backend>::value == category) && (boost::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3101 number<Backend, et_on> > ::type \
3102 func(const detail::expression<tag, A1, A2, A3, A4>& arg, number<Backend, et_on>&& a) \
3103 { \
3104 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3105 detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3106 } \
3107 template <class Backend, class Arithmetic> \
3108 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3109 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3110 number<Backend, et_on> >::type \
3111 func(number<Backend, et_on>&& arg, const Arithmetic& a) \
3112 { \
3113 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, \
3114 number<Backend, et_on>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3115 } \
3116 template <class Backend, class Arithmetic> \
3117 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3118 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3119 number<Backend, et_on> > ::type \
3120 func(const Arithmetic& arg, number<Backend, et_on>&& a) \
3121 { \
3122 return detail::expression< \
3123 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3124 Arithmetic, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3125 } \
3126
3127 #else
3128 #define UNARY_OP_FUNCTOR_CXX11_RVALUE(func, category)
3129 #define BINARY_OP_FUNCTOR_CXX11_RVALUE(func, category)
3130 #endif
3131
3132 #define UNARY_OP_FUNCTOR(func, category) \
3133 namespace detail { \
3134 template <class Backend> \
3135 struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3136 { \
3137 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const \
3138 { \
3139 using default_ops::BOOST_JOIN(eval_, func); \
3140 BOOST_JOIN(eval_, func) \
3141 (result, arg); \
3142 } \
3143 template <class U> \
3144 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg) const \
3145 { \
3146 using default_ops::BOOST_JOIN(eval_, func); \
3147 Backend temp; \
3148 BOOST_JOIN(eval_, func) \
3149 (temp, arg); \
3150 result = temp; \
3151 } \
3152 }; \
3153 } \
3154 \
3155 template <class tag, class A1, class A2, class A3, class A4> \
3156 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category, \
3157 detail::expression<detail::function, \
3158 detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3159 detail::expression<tag, A1, A2, A3, A4> > > ::type \
3160 func(const detail::expression<tag, A1, A2, A3, A4>& arg) \
3161 { \
3162 return detail::expression< \
3163 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3164 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); \
3165 } \
3166 template <class Backend> \
3167 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<Backend>::value == category, \
3168 detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, number<Backend, et_on> > > ::type \
3169 func(const number<Backend, et_on>& arg) \
3170 { \
3171 return detail::expression< \
3172 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3173 number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg); \
3174 } \
3175 template <class Backend> \
3176 inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c< \
3177 boost::multiprecision::number_category<Backend>::value == category, \
3178 number<Backend, et_off> >::type \
3179 func(const number<Backend, et_off>& arg) \
3180 { \
3181 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3182 number<Backend, et_off> result; \
3183 using default_ops::BOOST_JOIN(eval_, func); \
3184 BOOST_JOIN(eval_, func)(result.backend(), arg.backend()); \
3185 return result; \
3186 }\
3187 UNARY_OP_FUNCTOR_CXX11_RVALUE(func, category)\
3188
3189 #define BINARY_OP_FUNCTOR(func, category) \
3190 namespace detail { \
3191 template <class Backend> \
3192 struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3193 { \
3194 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg, const Backend& a) const \
3195 { \
3196 using default_ops::BOOST_JOIN(eval_, func); \
3197 BOOST_JOIN(eval_, func) \
3198 (result, arg, a); \
3199 } \
3200 template <class Arithmetic> \
3201 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg, const Arithmetic& a) const \
3202 { \
3203 using default_ops::BOOST_JOIN(eval_, func); \
3204 BOOST_JOIN(eval_, func) \
3205 (result, arg, number<Backend>::canonical_value(a)); \
3206 } \
3207 template <class Arithmetic> \
3208 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Arithmetic& arg, const Backend& a) const \
3209 { \
3210 using default_ops::BOOST_JOIN(eval_, func); \
3211 BOOST_JOIN(eval_, func) \
3212 (result, number<Backend>::canonical_value(arg), a); \
3213 } \
3214 template <class U> \
3215 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg, const Backend& a) const \
3216 { \
3217 using default_ops::BOOST_JOIN(eval_, func); \
3218 Backend r; \
3219 BOOST_JOIN(eval_, func) \
3220 (r, arg, a); \
3221 result = r; \
3222 } \
3223 template <class U, class Arithmetic> \
3224 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Backend& arg, const Arithmetic& a) const \
3225 { \
3226 using default_ops::BOOST_JOIN(eval_, func); \
3227 Backend r; \
3228 BOOST_JOIN(eval_, func) \
3229 (r, arg, number<Backend>::canonical_value(a)); \
3230 result = r; \
3231 } \
3232 template <class U, class Arithmetic> \
3233 BOOST_MP_CXX14_CONSTEXPR void operator()(U& result, const Arithmetic& arg, const Backend& a) const \
3234 { \
3235 using default_ops::BOOST_JOIN(eval_, func); \
3236 Backend r; \
3237 BOOST_JOIN(eval_, func) \
3238 (r, number<Backend>::canonical_value(arg), a); \
3239 result = r; \
3240 } \
3241 }; \
3242 } \
3243 template <class Backend> \
3244 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<Backend>::value == category, detail::expression<detail::function, \
3245 detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, number<Backend, et_on>, number<Backend, et_on> > > ::type \
3246 func(const number<Backend, et_on>& arg, const number<Backend, et_on>& a) \
3247 { \
3248 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3249 number<Backend, et_on>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3250 } \
3251 template <class Backend, class tag, class A1, class A2, class A3, class A4> \
3252 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(number_category<Backend>::value == category) && (boost::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3253 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 \
3254 func(const number<Backend, et_on>& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
3255 { \
3256 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3257 number<Backend, et_on>, detail::expression<tag, A1, A2, A3, A4> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3258 } \
3259 template <class tag, class A1, class A2, class A3, class A4, class Backend> \
3260 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(number_category<Backend>::value == category) && (boost::is_convertible<typename detail::expression<tag, A1, A2, A3, A4>::result_type, number<Backend, et_on> >::value), \
3261 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 \
3262 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const number<Backend, et_on>& a) \
3263 { \
3264 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3265 detail::expression<tag, A1, A2, A3, A4>, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3266 } \
3267 template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> \
3268 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category) && (number_category<detail::expression<tagb, A1b, A2b, A3b, A4b> >::value == category), \
3269 detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3270 detail::expression<tag, A1, A2, A3, A4>, detail::expression<tagb, A1b, A2b, A3b, A4b> > > ::type \
3271 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const detail::expression<tagb, A1b, A2b, A3b, A4b>& a) \
3272 { \
3273 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>, \
3274 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); \
3275 } \
3276 template <class Backend, class Arithmetic> \
3277 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3278 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3279 detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3280 number<Backend, et_on>, Arithmetic> > ::type \
3281 func(const number<Backend, et_on>& arg, const Arithmetic& a) \
3282 { \
3283 return detail::expression<detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>, \
3284 number<Backend, et_on>, Arithmetic > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct))<Backend>(), arg, a); \
3285 } \
3286 template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
3287 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3288 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), \
3289 detail::expression< \
3290 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3291 detail::expression<tag, A1, A2, A3, A4>, Arithmetic> > ::type \
3292 func(const detail::expression<tag, A1, A2, A3, A4>& arg, const Arithmetic& a) \
3293 { \
3294 return detail::expression< \
3295 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3296 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); \
3297 } \
3298 template <class Backend, class Arithmetic> \
3299 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3300 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_on> >::value && (number_category<Backend>::value == category), \
3301 detail::expression< \
3302 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3303 Arithmetic, number<Backend, et_on> > > ::type \
3304 func(const Arithmetic& arg, const number<Backend, et_on>& a) \
3305 { \
3306 return detail::expression< \
3307 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3308 Arithmetic, number<Backend, et_on> > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3309 } \
3310 template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
3311 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3312 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), \
3313 detail::expression< \
3314 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3315 Arithmetic, detail::expression<tag, A1, A2, A3, A4> > > ::type \
3316 func(const Arithmetic& arg, const detail::expression<tag, A1, A2, A3, A4>& a) \
3317 { \
3318 return detail::expression< \
3319 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3320 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); \
3321 } \
3322 template <class Backend> \
3323 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(number_category<Backend>::value == category), number<Backend, et_off> >::type \
3324 func(const number<Backend, et_off>& arg, const number<Backend, et_off>& a) \
3325 { \
3326 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
3327 number<Backend, et_off> result; \
3328 using default_ops::BOOST_JOIN(eval_, func); \
3329 BOOST_JOIN(eval_, func)(result.backend(), arg.backend(), a.backend()); \
3330 return result; \
3331 } \
3332 template <class Backend, class Arithmetic> \
3333 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3334 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
3335 number<Backend, et_off> >::type \
3336 func(const number<Backend, et_off>& arg, const Arithmetic& a) \
3337 { \
3338 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3339 number<Backend, et_off> result; \
3340 using default_ops::BOOST_JOIN(eval_, func); \
3341 BOOST_JOIN(eval_, func) \
3342 (result.backend(), arg.backend(), number<Backend, et_off>::canonical_value(a)); \
3343 return result; \
3344 } \
3345 template <class Backend, class Arithmetic> \
3346 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3347 is_compatible_arithmetic_type<Arithmetic, number<Backend, et_off> >::value && (number_category<Backend>::value == category), \
3348 number<Backend, et_off> >::type \
3349 func(const Arithmetic& a, const number<Backend, et_off>& arg) \
3350 { \
3351 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg); \
3352 number<Backend, et_off> result; \
3353 using default_ops::BOOST_JOIN(eval_, func); \
3354 BOOST_JOIN(eval_, func) \
3355 (result.backend(), number<Backend, et_off>::canonical_value(a), arg.backend()); \
3356 return result; \
3357 }\
3358 BINARY_OP_FUNCTOR_CXX11_RVALUE(func, category)
3359
3360 #define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category) \
3361 template <class tag, class A1, class A2, class A3, class A4> \
3362 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3363 (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category), \
3364 detail::expression< \
3365 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3366 detail::expression<tag, A1, A2, A3, A4>, Arg2> > ::type \
3367 func(const detail::expression<tag, A1, A2, A3, A4>& arg, Arg2 const& a) \
3368 { \
3369 return detail::expression< \
3370 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, \
3371 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); \
3372 } \
3373 template <class Backend> \
3374 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3375 (number_category<Backend>::value == category), \
3376 detail::expression< \
3377 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3378 number<Backend, et_on>, Arg2> > ::type \
3379 func(const number<Backend, et_on>& arg, Arg2 const& a) \
3380 { \
3381 return detail::expression< \
3382 detail::function, detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend>, \
3383 number<Backend, et_on>, Arg2 > (detail::BOOST_JOIN(category, BOOST_JOIN(func, _funct)) < Backend > (), arg, a); \
3384 } \
3385 template <class Backend> \
3386 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c< \
3387 (number_category<Backend>::value == category), \
3388 number<Backend, et_off> >::type \
3389 func(const number<Backend, et_off>& arg, Arg2 const& a) \
3390 { \
3391 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg, a); \
3392 number<Backend, et_off> result; \
3393 using default_ops::BOOST_JOIN(eval_, func); \
3394 BOOST_JOIN(eval_, func) \
3395 (result.backend(), arg.backend(), a); \
3396 return result; \
3397 }
3398
3399 #define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category) \
3400 namespace detail { \
3401 template <class Backend> \
3402 struct BOOST_JOIN(category, BOOST_JOIN(func, _funct)) \
3403 { \
3404 template <class Arg> \
3405 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, Backend const& arg, Arg a) const \
3406 { \
3407 using default_ops::BOOST_JOIN(eval_, func); \
3408 BOOST_JOIN(eval_, func) \
3409 (result, arg, a); \
3410 } \
3411 }; \
3412 } \
3413 \
3414 HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)
3415
3416 // clang-format on
3417
3418 namespace detail {
3419 template <class Backend>
3420 struct abs_funct
3421 {
operator ()boost::multiprecision::detail::abs_funct3422 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3423 {
3424 using default_ops::eval_abs;
3425 eval_abs(result, arg);
3426 }
3427 };
3428 template <class Backend>
3429 struct conj_funct
3430 {
operator ()boost::multiprecision::detail::conj_funct3431 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3432 {
3433 using default_ops::eval_conj;
3434 eval_conj(result, arg);
3435 }
3436 };
3437 template <class Backend>
3438 struct proj_funct
3439 {
operator ()boost::multiprecision::detail::proj_funct3440 BOOST_MP_CXX14_CONSTEXPR void operator()(Backend& result, const Backend& arg) const
3441 {
3442 using default_ops::eval_proj;
3443 eval_proj(result, arg);
3444 }
3445 };
3446
3447 } // namespace detail
3448
3449 template <class tag, class A1, class A2, class A3, class A4>
3450 inline BOOST_MP_CXX14_CONSTEXPR typename boost::disable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_complex,
3451 detail::expression<
3452 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
abs(const detail::expression<tag,A1,A2,A3,A4> & arg)3453 abs(const detail::expression<tag, A1, A2, A3, A4>& arg)
3454 {
3455 return detail::expression<
3456 detail::function, detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3457 detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3458 }
3459 template <class Backend>
3460 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<number_category<Backend>::value == number_kind_complex,
3461 detail::expression<
3462 detail::function, detail::abs_funct<Backend>, number<Backend, et_on> > >::type
abs(const number<Backend,et_on> & arg)3463 abs(const number<Backend, et_on>& arg)
3464 {
3465 return detail::expression<
3466 detail::function, detail::abs_funct<Backend>, number<Backend, et_on> >(
3467 detail::abs_funct<Backend>(), arg);
3468 }
3469 template <class Backend>
3470 inline BOOST_MP_CXX14_CONSTEXPR typename disable_if_c<number_category<Backend>::value == number_kind_complex, number<Backend, et_off> >::type
abs(const number<Backend,et_off> & arg)3471 abs(const number<Backend, et_off>& arg)
3472 {
3473 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3474 number<Backend, et_off> result;
3475 using default_ops::eval_abs;
3476 eval_abs(result.backend(), arg.backend());
3477 return result;
3478 }
3479
3480 template <class tag, class A1, class A2, class A3, class A4>
3481 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3482 detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
conj(const detail::expression<tag,A1,A2,A3,A4> & arg)3483 conj(const detail::expression<tag, A1, A2, A3, A4>& arg)
3484 {
3485 return detail::expression<
3486 detail::function, detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3487 detail::conj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3488 }
3489 template <class Backend>
3490 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3491 detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >
conj(const number<Backend,et_on> & arg)3492 conj(const number<Backend, et_on>& arg)
3493 {
3494 return detail::expression<
3495 detail::function, detail::conj_funct<Backend>, number<Backend, et_on> >(
3496 detail::conj_funct<Backend>(), arg);
3497 }
3498 template <class Backend>
3499 inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
conj(const number<Backend,et_off> & arg)3500 conj(const number<Backend, et_off>& arg)
3501 {
3502 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3503 number<Backend, et_off> result;
3504 using default_ops::eval_conj;
3505 eval_conj(result.backend(), arg.backend());
3506 return result;
3507 }
3508
3509 template <class tag, class A1, class A2, class A3, class A4>
3510 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3511 detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >
proj(const detail::expression<tag,A1,A2,A3,A4> & arg)3512 proj(const detail::expression<tag, A1, A2, A3, A4>& arg)
3513 {
3514 return detail::expression<
3515 detail::function, detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>, detail::expression<tag, A1, A2, A3, A4> >(
3516 detail::proj_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>(), arg);
3517 }
3518 template <class Backend>
3519 inline BOOST_MP_CXX14_CONSTEXPR detail::expression<
3520 detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >
proj(const number<Backend,et_on> & arg)3521 proj(const number<Backend, et_on>& arg)
3522 {
3523 return detail::expression<
3524 detail::function, detail::proj_funct<Backend>, number<Backend, et_on> >(
3525 detail::proj_funct<Backend>(), arg);
3526 }
3527 template <class Backend>
3528 inline BOOST_MP_CXX14_CONSTEXPR number<Backend, et_off>
proj(const number<Backend,et_off> & arg)3529 proj(const number<Backend, et_off>& arg)
3530 {
3531 detail::scoped_default_precision<multiprecision::number<Backend, et_off> > precision_guard(arg);
3532 number<Backend, et_off> result;
3533 using default_ops::eval_proj;
3534 eval_proj(result.backend(), arg.backend());
3535 return result;
3536 }
3537
UNARY_OP_FUNCTOR(fabs,number_kind_floating_point)3538 UNARY_OP_FUNCTOR(fabs, number_kind_floating_point)
3539 UNARY_OP_FUNCTOR(sqrt, number_kind_floating_point)
3540 UNARY_OP_FUNCTOR(floor, number_kind_floating_point)
3541 UNARY_OP_FUNCTOR(ceil, number_kind_floating_point)
3542 UNARY_OP_FUNCTOR(trunc, number_kind_floating_point)
3543 UNARY_OP_FUNCTOR(round, number_kind_floating_point)
3544 UNARY_OP_FUNCTOR(exp, number_kind_floating_point)
3545 UNARY_OP_FUNCTOR(exp2, number_kind_floating_point)
3546 UNARY_OP_FUNCTOR(log, number_kind_floating_point)
3547 UNARY_OP_FUNCTOR(log10, number_kind_floating_point)
3548 UNARY_OP_FUNCTOR(cos, number_kind_floating_point)
3549 UNARY_OP_FUNCTOR(sin, number_kind_floating_point)
3550 UNARY_OP_FUNCTOR(tan, number_kind_floating_point)
3551 UNARY_OP_FUNCTOR(asin, number_kind_floating_point)
3552 UNARY_OP_FUNCTOR(acos, number_kind_floating_point)
3553 UNARY_OP_FUNCTOR(atan, number_kind_floating_point)
3554 UNARY_OP_FUNCTOR(cosh, number_kind_floating_point)
3555 UNARY_OP_FUNCTOR(sinh, number_kind_floating_point)
3556 UNARY_OP_FUNCTOR(tanh, number_kind_floating_point)
3557 UNARY_OP_FUNCTOR(log2, number_kind_floating_point)
3558 UNARY_OP_FUNCTOR(nearbyint, number_kind_floating_point)
3559 UNARY_OP_FUNCTOR(rint, number_kind_floating_point)
3560
3561 HETERO_BINARY_OP_FUNCTOR(ldexp, short, number_kind_floating_point)
3562 //HETERO_BINARY_OP_FUNCTOR(frexp, short*, number_kind_floating_point)
3563 HETERO_BINARY_OP_FUNCTOR_B(ldexp, int, number_kind_floating_point)
3564 //HETERO_BINARY_OP_FUNCTOR_B(frexp, int*, number_kind_floating_point)
3565 HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point)
3566 //HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point)
3567 HETERO_BINARY_OP_FUNCTOR_B(ldexp, boost::long_long_type, number_kind_floating_point)
3568 //HETERO_BINARY_OP_FUNCTOR_B(frexp, boost::long_long_type*, number_kind_floating_point)
3569 BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
3570 BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
3571 BINARY_OP_FUNCTOR(fmax, number_kind_floating_point)
3572 BINARY_OP_FUNCTOR(fmin, number_kind_floating_point)
3573 BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
3574 BINARY_OP_FUNCTOR(fdim, number_kind_floating_point)
3575 BINARY_OP_FUNCTOR(hypot, number_kind_floating_point)
3576 BINARY_OP_FUNCTOR(remainder, number_kind_floating_point)
3577
3578 UNARY_OP_FUNCTOR(logb, number_kind_floating_point)
3579 HETERO_BINARY_OP_FUNCTOR(scalbn, short, number_kind_floating_point)
3580 HETERO_BINARY_OP_FUNCTOR(scalbln, short, number_kind_floating_point)
3581 HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point)
3582 HETERO_BINARY_OP_FUNCTOR_B(scalbln, int, number_kind_floating_point)
3583 HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point)
3584 HETERO_BINARY_OP_FUNCTOR_B(scalbln, long, number_kind_floating_point)
3585 HETERO_BINARY_OP_FUNCTOR_B(scalbn, boost::long_long_type, number_kind_floating_point)
3586 HETERO_BINARY_OP_FUNCTOR_B(scalbln, boost::long_long_type, number_kind_floating_point)
3587
3588 //
3589 // Complex functions:
3590 //
3591 UNARY_OP_FUNCTOR(exp, number_kind_complex)
3592 UNARY_OP_FUNCTOR(log, number_kind_complex)
3593 UNARY_OP_FUNCTOR(log10, number_kind_complex)
3594 BINARY_OP_FUNCTOR(pow, number_kind_complex)
3595 UNARY_OP_FUNCTOR(sqrt, number_kind_complex)
3596 UNARY_OP_FUNCTOR(sin, number_kind_complex)
3597 UNARY_OP_FUNCTOR(cos, number_kind_complex)
3598 UNARY_OP_FUNCTOR(tan, number_kind_complex)
3599 UNARY_OP_FUNCTOR(asin, number_kind_complex)
3600 UNARY_OP_FUNCTOR(acos, number_kind_complex)
3601 UNARY_OP_FUNCTOR(atan, number_kind_complex)
3602 UNARY_OP_FUNCTOR(sinh, number_kind_complex)
3603 UNARY_OP_FUNCTOR(cosh, number_kind_complex)
3604 UNARY_OP_FUNCTOR(tanh, number_kind_complex)
3605 UNARY_OP_FUNCTOR(asinh, number_kind_complex)
3606 UNARY_OP_FUNCTOR(acosh, number_kind_complex)
3607 UNARY_OP_FUNCTOR(atanh, number_kind_complex)
3608
3609 //
3610 // Integer functions:
3611 //
3612 BINARY_OP_FUNCTOR(gcd, number_kind_integer)
3613 BINARY_OP_FUNCTOR(lcm, number_kind_integer)
3614 HETERO_BINARY_OP_FUNCTOR(pow, unsigned, number_kind_integer)
3615
3616 #undef BINARY_OP_FUNCTOR
3617 #undef UNARY_OP_FUNCTOR
3618
3619 //
3620 // ilogb:
3621 //
3622 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
3623 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<Backend>::value == number_kind_floating_point, typename Backend::exponent_type>::type
3624 ilogb(const multiprecision::number<Backend, ExpressionTemplates>& val)
3625 {
3626 using default_ops::eval_ilogb;
3627 return eval_ilogb(val.backend());
3628 }
3629
3630 template <class tag, class A1, class A2, class A3, class A4>
3631 inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == number_kind_floating_point, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type::backend_type::exponent_type>::type
ilogb(const detail::expression<tag,A1,A2,A3,A4> & val)3632 ilogb(const detail::expression<tag, A1, A2, A3, A4>& val)
3633 {
3634 using default_ops::eval_ilogb;
3635 typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type arg(val);
3636 return eval_ilogb(arg.backend());
3637 }
3638
3639 } //namespace multiprecision
3640
3641 namespace math {
3642 //
3643 // Overload of Boost.Math functions that find the wrong overload when used with number:
3644 //
3645 namespace detail {
3646 template <class T>
3647 T sinc_pi_imp(T);
3648 template <class T>
3649 T sinhc_pi_imp(T);
3650 } // namespace detail
3651 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
sinc_pi(const multiprecision::number<Backend,ExpressionTemplates> & x)3652 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
3653 {
3654 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3655 return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
3656 }
3657
3658 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
sinc_pi(const multiprecision::number<Backend,ExpressionTemplates> & x,const Policy &)3659 inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
3660 {
3661 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3662 return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
3663 }
3664
3665 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
sinhc_pi(const multiprecision::number<Backend,ExpressionTemplates> & x)3666 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
3667 {
3668 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3669 return BOOST_MP_MOVE(detail::sinhc_pi_imp(x));
3670 }
3671
3672 template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
sinhc_pi(const multiprecision::number<Backend,ExpressionTemplates> & x,const Policy &)3673 inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
3674 {
3675 boost::multiprecision::detail::scoped_default_precision<multiprecision::number<Backend, ExpressionTemplates> > precision_guard(x);
3676 return BOOST_MP_MOVE(boost::math::sinhc_pi(x));
3677 }
3678
3679 using boost::multiprecision::gcd;
3680 using boost::multiprecision::lcm;
3681
3682 #ifdef BOOST_MSVC
3683 #pragma warning(pop)
3684 #endif
3685 } // namespace math
3686
3687 namespace integer {
3688
3689 using boost::multiprecision::gcd;
3690 using boost::multiprecision::lcm;
3691
3692 } // namespace integer
3693
3694 } // namespace boost
3695
3696 //
3697 // This has to come last of all:
3698 //
3699 #include <boost/multiprecision/detail/no_et_ops.hpp>
3700 #include <boost/multiprecision/detail/et_ops.hpp>
3701 //
3702 // min/max overloads:
3703 //
3704 #include <boost/multiprecision/detail/min_max.hpp>
3705
3706 #endif
3707