number_compare.hpp 24 KB

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