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