]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Copyright 2016 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_MP_MIN_MAX_HPP | |
7 | #define BOOST_MP_MIN_MAX_HPP | |
8 | ||
9 | #include <boost/multiprecision/traits/is_backend.hpp> | |
10 | ||
11 | namespace boost{ namespace multiprecision{ | |
12 | ||
13 | // | |
14 | // Expression template overloads for (min) and (max): | |
15 | // | |
16 | // Introduced in response to https://svn.boost.org/trac/boost/ticket/11149 | |
17 | // note that these can not legally be injected into namespace std, and that doing so | |
18 | // may break future enhancements to the standard. None the less adding | |
19 | // namespace std{ using boost::multiprecision::(min); using boost::multiprecision::(max); } | |
20 | // to your code may get some generic code working that wouldn't work otherwise. | |
21 | // | |
22 | // The use of enable_if on the return type is to avoid poisoning std::min/max, | |
23 | // otherwise attempting to make an explicit call to min<long>(a, b) when these and std | |
24 | // versions are in scope, will cause the compiler to try to instantiate the signatures | |
25 | // for our versions as well as the std ones, which in turn instantiates number<long> | |
26 | // which fails to compile as "long" is not a valid backend type. | |
27 | // | |
28 | template <class Backend> | |
29 | inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on>&>::type | |
30 | (min)(const number<Backend, et_on>& a, const number<Backend, et_on>& b) | |
31 | { | |
32 | return a < b ? a : b; | |
33 | } | |
34 | template <class Backend, class tag, class A1, class A2, class A3, class A4> | |
35 | inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type | |
36 | (min)(const number<Backend, et_on>& a, const detail::expression<tag, A1, A2, A3, A4>& b) | |
37 | { | |
38 | number<Backend, et_on> t(b); | |
39 | if(a < t) | |
40 | return a; | |
41 | return BOOST_MP_MOVE(t); | |
42 | } | |
43 | template <class tag, class A1, class A2, class A3, class A4, class Backend> | |
44 | inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type | |
45 | (min)(const detail::expression<tag, A1, A2, A3, A4>& a, const number<Backend, et_on>& b) | |
46 | { | |
47 | number<Backend, et_on> t(a); | |
48 | if(t < b) | |
49 | return BOOST_MP_MOVE(t); | |
50 | return b; | |
51 | } | |
52 | template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> | |
53 | inline typename detail::expression<tag, A1, A2, A3, A4>::result_type | |
54 | (min)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tagb, A1b, A2b, A3b, A4b>& b) | |
55 | { | |
56 | typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b); | |
57 | if(t1 < t2) | |
58 | return BOOST_MP_MOVE(t1); | |
59 | return BOOST_MP_MOVE(t2); | |
60 | } | |
61 | template <class tag, class A1, class A2, class A3, class A4> | |
62 | inline typename detail::expression<tag, A1, A2, A3, A4>::result_type (min)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tag, A1, A2, A3, A4>& b) | |
63 | { | |
64 | typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b); | |
65 | if(t1 < t2) | |
66 | return BOOST_MP_MOVE(t1); | |
67 | return BOOST_MP_MOVE(t2); | |
68 | } | |
69 | ||
70 | template <class Backend> | |
71 | inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on>&>::type | |
72 | (max)(const number<Backend, et_on>& a, const number<Backend, et_on>& b) | |
73 | { | |
74 | return a > b ? a : b; | |
75 | } | |
76 | template <class Backend, class tag, class A1, class A2, class A3, class A4> | |
77 | inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type | |
78 | (max)(const number<Backend, et_on>& a, const detail::expression<tag, A1, A2, A3, A4>& b) | |
79 | { | |
80 | number<Backend, et_on> t(b); | |
81 | if(a > t) | |
82 | return a; | |
83 | return BOOST_MP_MOVE(t); | |
84 | } | |
85 | template <class tag, class A1, class A2, class A3, class A4, class Backend> | |
86 | inline typename boost::enable_if_c < boost::multiprecision::detail::is_backend<Backend>::value, const number<Backend, et_on> >::type | |
87 | (max)(const detail::expression<tag, A1, A2, A3, A4>& a, const number<Backend, et_on>& b) | |
88 | { | |
89 | number<Backend, et_on> t(a); | |
90 | if(t > b) | |
91 | return BOOST_MP_MOVE(t); | |
92 | return b; | |
93 | } | |
94 | template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> | |
95 | inline typename detail::expression<tag, A1, A2, A3, A4>::result_type | |
96 | (max)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tagb, A1b, A2b, A3b, A4b>& b) | |
97 | { | |
98 | typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b); | |
99 | if(t1 > t2) | |
100 | return BOOST_MP_MOVE(t1); | |
101 | return BOOST_MP_MOVE(t2); | |
102 | } | |
103 | template <class tag, class A1, class A2, class A3, class A4> | |
104 | inline typename detail::expression<tag, A1, A2, A3, A4>::result_type (max)(const detail::expression<tag, A1, A2, A3, A4>& a, const detail::expression<tag, A1, A2, A3, A4>& b) | |
105 | { | |
106 | typename detail::expression<tag, A1, A2, A3, A4>::result_type t1(a), t2(b); | |
107 | if(t1 > t2) | |
108 | return BOOST_MP_MOVE(t1); | |
109 | return BOOST_MP_MOVE(t2); | |
110 | } | |
111 | ||
112 | }} // namespaces | |
113 | ||
114 | #endif |