number_compare.hpp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  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 typename boost::enable_if_c<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  240. operator < (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  241. {
  242. using default_ops::eval_lt;
  243. if(detail::is_unordered_comparison(a, b)) return false;
  244. return eval_lt(a.backend(), b.backend());
  245. }
  246. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  247. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  248. operator < (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  249. {
  250. using default_ops::eval_lt;
  251. if(detail::is_unordered_comparison(a, b)) return false;
  252. return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  253. }
  254. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  255. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  256. operator < (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  257. {
  258. using default_ops::eval_gt;
  259. if(detail::is_unordered_comparison(a, b)) return false;
  260. return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  261. }
  262. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  263. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  264. operator < (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  265. {
  266. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  267. using default_ops::eval_gt;
  268. result_type t(b);
  269. if(detail::is_unordered_comparison(a, t)) return false;
  270. return eval_gt(t.backend(), result_type::canonical_value(a));
  271. }
  272. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  273. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  274. operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  275. {
  276. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  277. using default_ops::eval_lt;
  278. result_type t(a);
  279. if(detail::is_unordered_comparison(t, b)) return false;
  280. return eval_lt(t.backend(), result_type::canonical_value(b));
  281. }
  282. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  283. inline typename enable_if_c<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  284. operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  285. {
  286. using default_ops::eval_lt;
  287. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  288. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  289. if(detail::is_unordered_comparison(t, t2)) return false;
  290. return eval_lt(t.backend(), t2.backend());
  291. }
  292. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  293. inline typename boost::enable_if_c<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  294. operator > (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  295. {
  296. using default_ops::eval_gt;
  297. if(detail::is_unordered_comparison(a, b)) return false;
  298. return eval_gt(a.backend(), b.backend());
  299. }
  300. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  301. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  302. operator > (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  303. {
  304. using default_ops::eval_gt;
  305. if(detail::is_unordered_comparison(a, b)) return false;
  306. return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  307. }
  308. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  309. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  310. operator > (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  311. {
  312. using default_ops::eval_lt;
  313. if(detail::is_unordered_comparison(a, b)) return false;
  314. return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  315. }
  316. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  317. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  318. operator > (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  319. {
  320. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  321. using default_ops::eval_lt;
  322. result_type t(b);
  323. if(detail::is_unordered_comparison(a, t)) return false;
  324. return a > t;
  325. }
  326. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  327. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  328. operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  329. {
  330. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  331. using default_ops::eval_gt;
  332. result_type t(a);
  333. if(detail::is_unordered_comparison(t, b)) return false;
  334. return t > b;
  335. }
  336. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  337. inline typename enable_if_c<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  338. operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  339. {
  340. using default_ops::eval_gt;
  341. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  342. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  343. if(detail::is_unordered_comparison(t, t2)) return false;
  344. return t > t2;
  345. }
  346. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  347. inline typename boost::enable_if_c<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  348. operator <= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  349. {
  350. using default_ops::eval_gt;
  351. if(detail::is_unordered_comparison(a, b)) return false;
  352. return !eval_gt(a.backend(), b.backend());
  353. }
  354. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  355. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  356. operator <= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  357. {
  358. using default_ops::eval_gt;
  359. if(detail::is_unordered_comparison(a, b)) return false;
  360. return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  361. }
  362. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  363. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  364. operator <= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  365. {
  366. using default_ops::eval_lt;
  367. if(detail::is_unordered_comparison(a, b)) return false;
  368. return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  369. }
  370. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  371. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  372. operator <= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  373. {
  374. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  375. using default_ops::eval_lt;
  376. if(detail::is_unordered_value(a) || detail::is_unordered_value(b))
  377. return false;
  378. result_type t(b);
  379. if(detail::is_unordered_comparison(a, t)) return false;
  380. return !eval_lt(t.backend(), result_type::canonical_value(a));
  381. }
  382. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  383. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  384. operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  385. {
  386. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  387. using default_ops::eval_gt;
  388. result_type t(a);
  389. if(detail::is_unordered_comparison(t, b)) return false;
  390. return !eval_gt(t.backend(), result_type::canonical_value(b));
  391. }
  392. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  393. inline typename enable_if_c<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  394. operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  395. {
  396. using default_ops::eval_gt;
  397. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  398. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  399. if(detail::is_unordered_comparison(t, t2)) return false;
  400. return !eval_gt(t.backend(), t2.backend());
  401. }
  402. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  403. inline typename boost::enable_if_c<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  404. operator >= (const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  405. {
  406. using default_ops::eval_lt;
  407. if(detail::is_unordered_comparison(a, b)) return false;
  408. return !eval_lt(a.backend(), b.backend());
  409. }
  410. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  411. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  412. operator >= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  413. {
  414. using default_ops::eval_lt;
  415. if(detail::is_unordered_comparison(a, b)) return false;
  416. return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  417. }
  418. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  419. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  420. operator >= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  421. {
  422. using default_ops::eval_gt;
  423. if(detail::is_unordered_comparison(a, b)) return false;
  424. return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  425. }
  426. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  427. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  428. operator >= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  429. {
  430. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  431. using default_ops::eval_gt;
  432. result_type t(b);
  433. if(detail::is_unordered_comparison(a, t)) return false;
  434. return !eval_gt(t.backend(), result_type::canonical_value(a));
  435. }
  436. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  437. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  438. operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  439. {
  440. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  441. using default_ops::eval_lt;
  442. result_type t(a);
  443. if(detail::is_unordered_comparison(t, b)) return false;
  444. return !eval_lt(t.backend(), result_type::canonical_value(b));
  445. }
  446. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  447. inline typename enable_if_c<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value && (number_category<typename detail::expression<Tag, A1, A2, A3, A4>::result_type>::value != number_kind_complex), bool>::type
  448. operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  449. {
  450. using default_ops::eval_lt;
  451. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  452. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  453. if(detail::is_unordered_comparison(t, t2)) return false;
  454. return !eval_lt(t.backend(), t2.backend());
  455. }
  456. //
  457. // C99 comparison macros as functions:
  458. //
  459. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  460. inline bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a > b; }
  461. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  462. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  463. isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a > b; }
  464. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  465. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  466. isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a > b; }
  467. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  468. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  469. isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a > b; }
  470. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  471. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  472. isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a > b; }
  473. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  474. 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
  475. isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a > b; }
  476. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  477. inline bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a >= b; }
  478. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  479. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  480. isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a >= b; }
  481. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  482. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  483. isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a >= b; }
  484. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  485. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  486. isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a >= b; }
  487. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  488. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  489. isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a >= b; }
  490. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  491. 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
  492. isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a >= b; }
  493. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  494. inline bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a <= b; }
  495. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  496. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  497. islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a <= b; }
  498. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  499. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  500. islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a <= b; }
  501. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  502. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  503. islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a <= b; }
  504. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  505. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  506. islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a <= b; }
  507. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  508. 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
  509. islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a <= b; }
  510. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  511. inline bool isless BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a < b; }
  512. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  513. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  514. isless BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a < b; }
  515. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  516. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  517. isless BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a < b; }
  518. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  519. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  520. isless BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a < b; }
  521. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  522. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  523. isless BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a < b; }
  524. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  525. 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
  526. isless BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b) { return a < b; }
  527. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  528. inline bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  529. {
  530. if(detail::is_unordered_comparison(a, b)) return false;
  531. return a != b;
  532. }
  533. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  534. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  535. islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  536. {
  537. if(detail::is_unordered_comparison(a, b)) return false;
  538. return a != b;
  539. }
  540. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  541. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  542. islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  543. {
  544. if(detail::is_unordered_comparison(a, b)) return false;
  545. return a != b;
  546. }
  547. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  548. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  549. islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
  550. {
  551. typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
  552. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  553. }
  554. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  555. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  556. islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
  557. {
  558. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  559. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  560. }
  561. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  562. 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
  563. islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
  564. {
  565. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  566. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
  567. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  568. }
  569. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  570. inline bool isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return detail::is_unordered_comparison(a, b); }
  571. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  572. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  573. isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return detail::is_unordered_comparison(a, b); }
  574. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  575. inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  576. isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return detail::is_unordered_comparison(a, b); }
  577. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  578. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  579. isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
  580. {
  581. typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
  582. return detail::is_unordered_comparison(a, b);
  583. }
  584. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  585. inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  586. isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
  587. {
  588. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  589. return detail::is_unordered_comparison(a, b);
  590. }
  591. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  592. 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
  593. isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
  594. {
  595. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  596. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
  597. return detail::is_unordered_comparison(a, b);
  598. }
  599. }} // namespaces
  600. #endif // BOOST_MP_COMPARE_HPP