1 ///////////////////////////////////////////////////////////////////////////////
2 //  Copyright 2012 John Maddock. Distributed under the Boost
3 //  Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef BOOST_MP_COMPARE_HPP
7 #define BOOST_MP_COMPARE_HPP
8 
9 #include <boost/multiprecision/traits/is_backend.hpp>
10 
11 //
12 // Comparison operators for number.
13 //
14 
15 namespace boost{ namespace multiprecision{
16 
17 namespace default_ops{
18 
19 //
20 // The dispatching mechanism used here to deal with differently typed arguments
21 // could be better replaced with enable_if overloads, but that breaks MSVC-12
22 // under strange and hard to reproduce circumstances.
23 //
24 template <class B>
eval_eq(const B & a,const B & b)25 inline bool eval_eq(const B& a, const B& b)
26 {
27    return a.compare(b) == 0;
28 }
29 template <class T, class U>
eval_eq_imp(const T & a,const U & b,const mpl::true_ &)30 inline bool eval_eq_imp(const T& a, const U& b, const mpl::true_&)
31 {
32    typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
33    return eval_eq(a, t.backend());
34 }
35 template <class T, class U>
eval_eq_imp(const T & a,const U & b,const mpl::false_ &)36 inline bool eval_eq_imp(const T& a, const U& b, const mpl::false_&)
37 {
38    typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
39    return eval_eq(t.backend(), b);
40 }
41 template <class T, class U>
eval_eq(const T & a,const U & b)42 inline bool eval_eq(const T& a, const U& b)
43 {
44    typedef mpl::bool_<boost::multiprecision::detail::is_first_backend<T, U>::value> tag_type;
45    return eval_eq_imp(a, b, tag_type());
46 }
47 
48 template <class B>
eval_lt(const B & a,const B & b)49 inline bool eval_lt(const B& a, const B& b)
50 {
51    return a.compare(b) < 0;
52 }
53 template <class T, class U>
eval_lt_imp(const T & a,const U & b,const mpl::true_ &)54 inline bool eval_lt_imp(const T& a, const U& b, const mpl::true_&)
55 {
56    typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
57    return eval_lt(a, t.backend());
58 }
59 template <class T, class U>
eval_lt_imp(const T & a,const U & b,const mpl::false_ &)60 inline bool eval_lt_imp(const T& a, const U& b, const mpl::false_&)
61 {
62    typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
63    return eval_lt(t.backend(), b);
64 }
65 template <class T, class U>
eval_lt(const T & a,const U & b)66 inline bool eval_lt(const T& a, const U& b)
67 {
68    typedef mpl::bool_<boost::multiprecision::detail::is_first_backend<T, U>::value> tag_type;
69    return eval_lt_imp(a, b, tag_type());
70 }
71 
72 template <class B>
eval_gt(const B & a,const B & b)73 inline bool eval_gt(const B& a, const B& b)
74 {
75    return a.compare(b) > 0;
76 }
77 template <class T, class U>
eval_gt_imp(const T & a,const U & b,const mpl::true_ &)78 inline bool eval_gt_imp(const T& a, const U& b, const mpl::true_&)
79 {
80    typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
81    return eval_gt(a, t.backend());
82 }
83 template <class T, class U>
eval_gt_imp(const T & a,const U & b,const mpl::false_ &)84 inline bool eval_gt_imp(const T& a, const U& b, const mpl::false_&)
85 {
86    typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
87    return eval_gt(t.backend(), b);
88 }
89 template <class T, class U>
eval_gt(const T & a,const U & b)90 inline bool eval_gt(const T& a, const U& b)
91 {
92    typedef mpl::bool_<boost::multiprecision::detail::is_first_backend<T, U>::value> tag_type;
93    return eval_gt_imp(a, b, tag_type());
94 }
95 
96 } // namespace default_ops
97 
98 namespace detail{
99 
100 template <class Num, class Val>
101 struct is_valid_mixed_compare : public mpl::false_ {};
102 
103 template <class B, expression_template_option ET, class Val>
104 struct is_valid_mixed_compare<number<B, ET>, Val> : public is_convertible<Val, number<B, ET> > {};
105 
106 template <class B, expression_template_option ET>
107 struct is_valid_mixed_compare<number<B, ET>, number<B, ET> > : public mpl::false_ {};
108 
109 template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
110 struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> >
111    : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {};
112 
113 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
114 struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
115    : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {};
116 
117 template <class Backend, expression_template_option ExpressionTemplates>
is_unordered_value(const number<Backend,ExpressionTemplates> &)118 inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value != number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>&)
119 {
120    return false;
121 }
122 template <class Backend, expression_template_option ExpressionTemplates>
is_unordered_value(const number<Backend,ExpressionTemplates> & a)123 inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Backend>::value == number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>& a)
124 {
125    using default_ops::eval_fpclassify;
126    return eval_fpclassify(a.backend()) == FP_NAN;
127 }
128 
129 template <class Arithmetic>
is_unordered_value(const Arithmetic &)130 inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Arithmetic>::value != number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic&)
131 {
132    return false;
133 }
134 template <class Arithmetic>
is_unordered_value(const Arithmetic & a)135 inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Arithmetic>::value == number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic& a)
136 {
137    return (boost::math::isnan)(a);
138 }
139 
140 template <class T, class U>
is_unordered_comparison(const T & a,const U & b)141 inline BOOST_CONSTEXPR bool is_unordered_comparison(const T& a, const U& b)
142 {
143    return is_unordered_value(a) || is_unordered_value(b);
144 }
145 
146 }
147 
148 template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
operator ==(const number<Backend,ExpressionTemplates> & a,const number<Backend2,ExpressionTemplates2> & b)149 inline bool operator == (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
150 {
151    using default_ops::eval_eq;
152    if(detail::is_unordered_comparison(a, b)) return false;
153    return eval_eq(a.backend(), b.backend());
154 }
155 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
156 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator ==(const number<Backend,ExpressionTemplates> & a,const Arithmetic & b)157    operator == (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
158 {
159    using default_ops::eval_eq;
160    if(detail::is_unordered_comparison(a, b)) return false;
161    return eval_eq(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
162 }
163 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
164 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator ==(const Arithmetic & a,const number<Backend,ExpressionTemplates> & b)165    operator == (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
166 {
167    using default_ops::eval_eq;
168    if(detail::is_unordered_comparison(a, b)) return false;
169    return eval_eq(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
170 }
171 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
172 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator ==(const Arithmetic & a,const detail::expression<Tag,A1,A2,A3,A4> & b)173    operator == (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
174 {
175    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
176    using default_ops::eval_eq;
177    result_type t(b);
178    if(detail::is_unordered_comparison(a, t)) return false;
179    return eval_eq(t.backend(), result_type::canonical_value(a));
180 }
181 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
182 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator ==(const detail::expression<Tag,A1,A2,A3,A4> & a,const Arithmetic & b)183    operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
184 {
185    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
186    using default_ops::eval_eq;
187    result_type t(a);
188    if(detail::is_unordered_comparison(t, b)) return false;
189    return eval_eq(t.backend(), result_type::canonical_value(b));
190 }
191 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
192 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
operator ==(const detail::expression<Tag,A1,A2,A3,A4> & a,const detail::expression<Tagb,A1b,A2b,A3b,A4b> & b)193    operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
194 {
195    using default_ops::eval_eq;
196    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
197    typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
198    if(detail::is_unordered_comparison(t, t2)) return false;
199    return eval_eq(t.backend(), t2.backend());
200 }
201 
202 template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
operator !=(const number<Backend,ExpressionTemplates> & a,const number<Backend2,ExpressionTemplates2> & b)203 inline bool operator != (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
204 {
205    using default_ops::eval_eq;
206    if(detail::is_unordered_comparison(a, b)) return true;
207    return !eval_eq(a.backend(), b.backend());
208 }
209 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
210 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator !=(const number<Backend,ExpressionTemplates> & a,const Arithmetic & b)211    operator != (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
212 {
213    using default_ops::eval_eq;
214    if(detail::is_unordered_comparison(a, b)) return true;
215    return !eval_eq(a.backend(), number<Backend, et_on>::canonical_value(b));
216 }
217 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
218 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator !=(const Arithmetic & a,const number<Backend,ExpressionTemplates> & b)219    operator != (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
220 {
221    using default_ops::eval_eq;
222    if(detail::is_unordered_comparison(a, b)) return true;
223    return !eval_eq(b.backend(), number<Backend, et_on>::canonical_value(a));
224 }
225 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
226 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator !=(const Arithmetic & a,const detail::expression<Tag,A1,A2,A3,A4> & b)227    operator != (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
228 {
229    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
230    using default_ops::eval_eq;
231    result_type t(b);
232    if(detail::is_unordered_comparison(a, t)) return true;
233    return !eval_eq(t.backend(), result_type::canonical_value(a));
234 }
235 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
236 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator !=(const detail::expression<Tag,A1,A2,A3,A4> & a,const Arithmetic & b)237    operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
238 {
239    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
240    using default_ops::eval_eq;
241    result_type t(a);
242    if(detail::is_unordered_comparison(t, b)) return true;
243    return !eval_eq(t.backend(), result_type::canonical_value(b));
244 }
245 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
246 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
operator !=(const detail::expression<Tag,A1,A2,A3,A4> & a,const detail::expression<Tagb,A1b,A2b,A3b,A4b> & b)247    operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
248 {
249    using default_ops::eval_eq;
250    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
251    typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
252    if(detail::is_unordered_comparison(t, t2)) return true;
253    return !eval_eq(t.backend(), t2.backend());
254 }
255 
256 template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
operator <(const number<Backend,ExpressionTemplates> & a,const number<Backend2,ExpressionTemplates2> & b)257 inline bool operator < (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
258 {
259    using default_ops::eval_lt;
260    if(detail::is_unordered_comparison(a, b)) return false;
261    return eval_lt(a.backend(), b.backend());
262 }
263 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
264 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator <(const number<Backend,ExpressionTemplates> & a,const Arithmetic & b)265    operator < (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
266 {
267    using default_ops::eval_lt;
268    if(detail::is_unordered_comparison(a, b)) return false;
269    return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
270 }
271 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
272 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator <(const Arithmetic & a,const number<Backend,ExpressionTemplates> & b)273    operator < (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
274 {
275    using default_ops::eval_gt;
276    if(detail::is_unordered_comparison(a, b)) return false;
277    return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
278 }
279 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
280 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator <(const Arithmetic & a,const detail::expression<Tag,A1,A2,A3,A4> & b)281    operator < (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
282 {
283    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
284    using default_ops::eval_gt;
285    result_type t(b);
286    if(detail::is_unordered_comparison(a, t)) return false;
287    return eval_gt(t.backend(), result_type::canonical_value(a));
288 }
289 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
290 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator <(const detail::expression<Tag,A1,A2,A3,A4> & a,const Arithmetic & b)291    operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
292 {
293    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
294    using default_ops::eval_lt;
295    result_type t(a);
296    if(detail::is_unordered_comparison(t, b)) return false;
297    return eval_lt(t.backend(), result_type::canonical_value(b));
298 }
299 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
300 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
operator <(const detail::expression<Tag,A1,A2,A3,A4> & a,const detail::expression<Tagb,A1b,A2b,A3b,A4b> & b)301    operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
302 {
303    using default_ops::eval_lt;
304    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
305    typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
306    if(detail::is_unordered_comparison(t, t2)) return false;
307    return eval_lt(t.backend(), t2.backend());
308 }
309 
310 template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
operator >(const number<Backend,ExpressionTemplates> & a,const number<Backend2,ExpressionTemplates2> & b)311 inline bool operator > (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
312 {
313    using default_ops::eval_gt;
314    if(detail::is_unordered_comparison(a, b)) return false;
315    return eval_gt(a.backend(), b.backend());
316 }
317 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
318 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator >(const number<Backend,ExpressionTemplates> & a,const Arithmetic & b)319    operator > (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
320 {
321    using default_ops::eval_gt;
322    if(detail::is_unordered_comparison(a, b)) return false;
323    return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
324 }
325 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
326 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator >(const Arithmetic & a,const number<Backend,ExpressionTemplates> & b)327    operator > (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
328 {
329    using default_ops::eval_lt;
330    if(detail::is_unordered_comparison(a, b)) return false;
331    return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
332 }
333 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
334 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator >(const Arithmetic & a,const detail::expression<Tag,A1,A2,A3,A4> & b)335    operator > (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
336 {
337    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
338    using default_ops::eval_lt;
339    result_type t(b);
340    if(detail::is_unordered_comparison(a, t)) return false;
341    return a > t;
342 }
343 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
344 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator >(const detail::expression<Tag,A1,A2,A3,A4> & a,const Arithmetic & b)345    operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
346 {
347    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
348    using default_ops::eval_gt;
349    result_type t(a);
350    if(detail::is_unordered_comparison(t, b)) return false;
351    return t > b;
352 }
353 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
354 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
operator >(const detail::expression<Tag,A1,A2,A3,A4> & a,const detail::expression<Tagb,A1b,A2b,A3b,A4b> & b)355    operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
356 {
357    using default_ops::eval_gt;
358    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
359    typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
360    if(detail::is_unordered_comparison(t, t2)) return false;
361    return t > t2;
362 }
363 
364 template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
operator <=(const number<Backend,ExpressionTemplates> & a,const number<Backend2,ExpressionTemplates2> & b)365 inline bool operator <= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
366 {
367    using default_ops::eval_gt;
368    if(detail::is_unordered_comparison(a, b)) return false;
369    return !eval_gt(a.backend(), b.backend());
370 }
371 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
372 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator <=(const number<Backend,ExpressionTemplates> & a,const Arithmetic & b)373    operator <= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
374 {
375    using default_ops::eval_gt;
376    if(detail::is_unordered_comparison(a, b)) return false;
377    return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
378 }
379 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
380 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator <=(const Arithmetic & a,const number<Backend,ExpressionTemplates> & b)381    operator <= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
382 {
383    using default_ops::eval_lt;
384    if(detail::is_unordered_comparison(a, b)) return false;
385    return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
386 }
387 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
388 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator <=(const Arithmetic & a,const detail::expression<Tag,A1,A2,A3,A4> & b)389    operator <= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
390 {
391    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
392    using default_ops::eval_lt;
393    if(detail::is_unordered_value(a) || detail::is_unordered_value(b))
394       return false;
395    result_type t(b);
396    if(detail::is_unordered_comparison(a, t)) return false;
397    return !eval_lt(t.backend(), result_type::canonical_value(a));
398 }
399 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
400 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator <=(const detail::expression<Tag,A1,A2,A3,A4> & a,const Arithmetic & b)401    operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
402 {
403    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
404    using default_ops::eval_gt;
405    result_type t(a);
406    if(detail::is_unordered_comparison(t, b)) return false;
407    return !eval_gt(t.backend(), result_type::canonical_value(b));
408 }
409 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
410 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
operator <=(const detail::expression<Tag,A1,A2,A3,A4> & a,const detail::expression<Tagb,A1b,A2b,A3b,A4b> & b)411    operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
412 {
413    using default_ops::eval_gt;
414    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
415    typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
416    if(detail::is_unordered_comparison(t, t2)) return false;
417    return !eval_gt(t.backend(), t2.backend());
418 }
419 
420 template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
operator >=(const number<Backend,ExpressionTemplates> & a,const number<Backend2,ExpressionTemplates2> & b)421 inline bool operator >= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
422 {
423    using default_ops::eval_lt;
424    if(detail::is_unordered_comparison(a, b)) return false;
425    return !eval_lt(a.backend(), b.backend());
426 }
427 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
428 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator >=(const number<Backend,ExpressionTemplates> & a,const Arithmetic & b)429    operator >= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
430 {
431    using default_ops::eval_lt;
432    if(detail::is_unordered_comparison(a, b)) return false;
433    return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
434 }
435 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
436 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
operator >=(const Arithmetic & a,const number<Backend,ExpressionTemplates> & b)437    operator >= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
438 {
439    using default_ops::eval_gt;
440    if(detail::is_unordered_comparison(a, b)) return false;
441    return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
442 }
443 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
444 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator >=(const Arithmetic & a,const detail::expression<Tag,A1,A2,A3,A4> & b)445    operator >= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
446 {
447    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
448    using default_ops::eval_gt;
449    result_type t(b);
450    if(detail::is_unordered_comparison(a, t)) return false;
451    return !eval_gt(t.backend(), result_type::canonical_value(a));
452 }
453 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
454 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
operator >=(const detail::expression<Tag,A1,A2,A3,A4> & a,const Arithmetic & b)455    operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
456 {
457    typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
458    using default_ops::eval_lt;
459    result_type t(a);
460    if(detail::is_unordered_comparison(t, b)) return false;
461    return !eval_lt(t.backend(), result_type::canonical_value(b));
462 }
463 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
464 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
operator >=(const detail::expression<Tag,A1,A2,A3,A4> & a,const detail::expression<Tagb,A1b,A2b,A3b,A4b> & b)465    operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
466 {
467    using default_ops::eval_lt;
468    typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
469    typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
470    if(detail::is_unordered_comparison(t, t2)) return false;
471    return !eval_lt(t.backend(), t2.backend());
472 }
473 
474 
475 }} // namespaces
476 
477 #endif // BOOST_MP_COMPARE_HPP
478 
479