number_compare.hpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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 BOOST_MP_CXX14_CONSTEXPR 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. {};
  92. template <class B, expression_template_option ET, class Val>
  93. struct is_valid_mixed_compare<number<B, ET>, Val> : public is_convertible<Val, number<B, ET> >
  94. {};
  95. template <class B, expression_template_option ET>
  96. struct is_valid_mixed_compare<number<B, ET>, number<B, ET> > : public mpl::false_
  97. {};
  98. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  99. struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> >
  100. : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value>
  101. {};
  102. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  103. struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  104. : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value>
  105. {};
  106. template <class Backend, expression_template_option ExpressionTemplates>
  107. 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>&)
  108. {
  109. return false;
  110. }
  111. template <class Backend, expression_template_option ExpressionTemplates>
  112. inline
  113. #if !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)
  114. BOOST_CONSTEXPR
  115. #endif
  116. typename boost::enable_if_c<number_category<Backend>::value == number_kind_floating_point, bool>::type
  117. is_unordered_value(const number<Backend, ExpressionTemplates>& a)
  118. {
  119. using default_ops::eval_fpclassify;
  120. return eval_fpclassify(a.backend()) == FP_NAN;
  121. }
  122. template <class Arithmetic>
  123. inline BOOST_CONSTEXPR typename boost::enable_if_c<number_category<Arithmetic>::value != number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic&)
  124. {
  125. return false;
  126. }
  127. template <class Arithmetic>
  128. inline
  129. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  130. BOOST_MP_CXX14_CONSTEXPR
  131. #endif
  132. typename boost::enable_if_c < number_category < Arithmetic> ::value == number_kind_floating_point, bool> ::type
  133. is_unordered_value(const Arithmetic& a)
  134. {
  135. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  136. if (BOOST_MP_IS_CONST_EVALUATED(a))
  137. {
  138. return a != a;
  139. }
  140. else
  141. #endif
  142. {
  143. return (boost::math::isnan)(a);
  144. }
  145. }
  146. template <class T, class U>
  147. inline BOOST_CONSTEXPR bool is_unordered_comparison(const T& a, const U& b)
  148. {
  149. return is_unordered_value(a) || is_unordered_value(b);
  150. }
  151. } // namespace detail
  152. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  153. inline BOOST_MP_CXX14_CONSTEXPR bool operator==(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  154. {
  155. using default_ops::eval_eq;
  156. if (detail::is_unordered_comparison(a, b))
  157. return false;
  158. return eval_eq(a.backend(), b.backend());
  159. }
  160. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  161. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  162. operator==(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  163. {
  164. using default_ops::eval_eq;
  165. if (detail::is_unordered_comparison(a, b))
  166. return false;
  167. return eval_eq(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  168. }
  169. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  170. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  171. operator==(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  172. {
  173. using default_ops::eval_eq;
  174. if (detail::is_unordered_comparison(a, b))
  175. return false;
  176. return eval_eq(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  177. }
  178. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  179. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  180. operator==(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  181. {
  182. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  183. using default_ops::eval_eq;
  184. result_type t(b);
  185. if (detail::is_unordered_comparison(a, t))
  186. return false;
  187. return eval_eq(t.backend(), result_type::canonical_value(a));
  188. }
  189. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  190. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  191. operator==(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  192. {
  193. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  194. using default_ops::eval_eq;
  195. result_type t(a);
  196. if (detail::is_unordered_comparison(t, b))
  197. return false;
  198. return eval_eq(t.backend(), result_type::canonical_value(b));
  199. }
  200. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  201. inline BOOST_MP_CXX14_CONSTEXPR 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
  202. operator==(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  203. {
  204. using default_ops::eval_eq;
  205. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  206. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  207. if (detail::is_unordered_comparison(t, t2))
  208. return false;
  209. return eval_eq(t.backend(), t2.backend());
  210. }
  211. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  212. inline BOOST_MP_CXX14_CONSTEXPR bool operator!=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  213. {
  214. using default_ops::eval_eq;
  215. if (detail::is_unordered_comparison(a, b))
  216. return true;
  217. return !eval_eq(a.backend(), b.backend());
  218. }
  219. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  220. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  221. operator!=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  222. {
  223. using default_ops::eval_eq;
  224. if (detail::is_unordered_comparison(a, b))
  225. return true;
  226. return !eval_eq(a.backend(), number<Backend, et_on>::canonical_value(b));
  227. }
  228. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  229. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  230. operator!=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  231. {
  232. using default_ops::eval_eq;
  233. if (detail::is_unordered_comparison(a, b))
  234. return true;
  235. return !eval_eq(b.backend(), number<Backend, et_on>::canonical_value(a));
  236. }
  237. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  238. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  239. operator!=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  240. {
  241. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  242. using default_ops::eval_eq;
  243. result_type t(b);
  244. if (detail::is_unordered_comparison(a, t))
  245. return true;
  246. return !eval_eq(t.backend(), result_type::canonical_value(a));
  247. }
  248. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  249. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  250. operator!=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  251. {
  252. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  253. using default_ops::eval_eq;
  254. result_type t(a);
  255. if (detail::is_unordered_comparison(t, b))
  256. return true;
  257. return !eval_eq(t.backend(), result_type::canonical_value(b));
  258. }
  259. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  260. inline BOOST_MP_CXX14_CONSTEXPR 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
  261. operator!=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  262. {
  263. using default_ops::eval_eq;
  264. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  265. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  266. if (detail::is_unordered_comparison(t, t2))
  267. return true;
  268. return !eval_eq(t.backend(), t2.backend());
  269. }
  270. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  271. inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  272. operator<(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  273. {
  274. using default_ops::eval_lt;
  275. if (detail::is_unordered_comparison(a, b))
  276. return false;
  277. return eval_lt(a.backend(), b.backend());
  278. }
  279. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  280. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  281. operator<(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  282. {
  283. using default_ops::eval_lt;
  284. if (detail::is_unordered_comparison(a, b))
  285. return false;
  286. return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  287. }
  288. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  289. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  290. operator<(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  291. {
  292. using default_ops::eval_gt;
  293. if (detail::is_unordered_comparison(a, b))
  294. return false;
  295. return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  296. }
  297. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  298. inline BOOST_MP_CXX14_CONSTEXPR 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
  299. operator<(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  300. {
  301. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  302. using default_ops::eval_gt;
  303. result_type t(b);
  304. if (detail::is_unordered_comparison(a, t))
  305. return false;
  306. return eval_gt(t.backend(), result_type::canonical_value(a));
  307. }
  308. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  309. inline BOOST_MP_CXX14_CONSTEXPR 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
  310. operator<(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  311. {
  312. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  313. using default_ops::eval_lt;
  314. result_type t(a);
  315. if (detail::is_unordered_comparison(t, b))
  316. return false;
  317. return eval_lt(t.backend(), result_type::canonical_value(b));
  318. }
  319. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  320. inline BOOST_MP_CXX14_CONSTEXPR 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
  321. operator<(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  322. {
  323. using default_ops::eval_lt;
  324. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  325. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  326. if (detail::is_unordered_comparison(t, t2))
  327. return false;
  328. return eval_lt(t.backend(), t2.backend());
  329. }
  330. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  331. inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  332. operator>(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  333. {
  334. using default_ops::eval_gt;
  335. if (detail::is_unordered_comparison(a, b))
  336. return false;
  337. return eval_gt(a.backend(), b.backend());
  338. }
  339. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  340. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  341. operator>(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  342. {
  343. using default_ops::eval_gt;
  344. if (detail::is_unordered_comparison(a, b))
  345. return false;
  346. return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  347. }
  348. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  349. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  350. operator>(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  351. {
  352. using default_ops::eval_lt;
  353. if (detail::is_unordered_comparison(a, b))
  354. return false;
  355. return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  356. }
  357. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  358. inline BOOST_MP_CXX14_CONSTEXPR 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
  359. operator>(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  360. {
  361. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  362. using default_ops::eval_lt;
  363. result_type t(b);
  364. if (detail::is_unordered_comparison(a, t))
  365. return false;
  366. return a > t;
  367. }
  368. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  369. inline BOOST_MP_CXX14_CONSTEXPR 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
  370. operator>(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  371. {
  372. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  373. using default_ops::eval_gt;
  374. result_type t(a);
  375. if (detail::is_unordered_comparison(t, b))
  376. return false;
  377. return t > b;
  378. }
  379. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  380. inline BOOST_MP_CXX14_CONSTEXPR 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
  381. operator>(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  382. {
  383. using default_ops::eval_gt;
  384. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  385. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  386. if (detail::is_unordered_comparison(t, t2))
  387. return false;
  388. return t > t2;
  389. }
  390. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  391. inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  392. operator<=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  393. {
  394. using default_ops::eval_gt;
  395. if (detail::is_unordered_comparison(a, b))
  396. return false;
  397. return !eval_gt(a.backend(), b.backend());
  398. }
  399. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  400. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  401. operator<=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  402. {
  403. using default_ops::eval_gt;
  404. if (detail::is_unordered_comparison(a, b))
  405. return false;
  406. return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  407. }
  408. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  409. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  410. operator<=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  411. {
  412. using default_ops::eval_lt;
  413. if (detail::is_unordered_comparison(a, b))
  414. return false;
  415. return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  416. }
  417. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  418. inline BOOST_MP_CXX14_CONSTEXPR 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
  419. operator<=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  420. {
  421. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  422. using default_ops::eval_lt;
  423. if (detail::is_unordered_value(a) || detail::is_unordered_value(b))
  424. return false;
  425. result_type t(b);
  426. if (detail::is_unordered_comparison(a, t))
  427. return false;
  428. return !eval_lt(t.backend(), result_type::canonical_value(a));
  429. }
  430. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  431. inline BOOST_MP_CXX14_CONSTEXPR 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
  432. operator<=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  433. {
  434. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  435. using default_ops::eval_gt;
  436. result_type t(a);
  437. if (detail::is_unordered_comparison(t, b))
  438. return false;
  439. return !eval_gt(t.backend(), result_type::canonical_value(b));
  440. }
  441. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  442. inline BOOST_MP_CXX14_CONSTEXPR 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
  443. operator<=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  444. {
  445. using default_ops::eval_gt;
  446. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  447. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  448. if (detail::is_unordered_comparison(t, t2))
  449. return false;
  450. return !eval_gt(t.backend(), t2.backend());
  451. }
  452. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  453. inline BOOST_MP_CXX14_CONSTEXPR typename boost::enable_if_c<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  454. operator>=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  455. {
  456. using default_ops::eval_lt;
  457. if (detail::is_unordered_comparison(a, b))
  458. return false;
  459. return !eval_lt(a.backend(), b.backend());
  460. }
  461. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  462. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  463. operator>=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  464. {
  465. using default_ops::eval_lt;
  466. if (detail::is_unordered_comparison(a, b))
  467. return false;
  468. return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  469. }
  470. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  471. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex), bool>::type
  472. operator>=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  473. {
  474. using default_ops::eval_gt;
  475. if (detail::is_unordered_comparison(a, b))
  476. return false;
  477. return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  478. }
  479. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  480. inline BOOST_MP_CXX14_CONSTEXPR 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
  481. operator>=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  482. {
  483. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  484. using default_ops::eval_gt;
  485. result_type t(b);
  486. if (detail::is_unordered_comparison(a, t))
  487. return false;
  488. return !eval_gt(t.backend(), result_type::canonical_value(a));
  489. }
  490. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  491. inline BOOST_MP_CXX14_CONSTEXPR 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
  492. operator>=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  493. {
  494. typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
  495. using default_ops::eval_lt;
  496. result_type t(a);
  497. if (detail::is_unordered_comparison(t, b))
  498. return false;
  499. return !eval_lt(t.backend(), result_type::canonical_value(b));
  500. }
  501. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  502. inline BOOST_MP_CXX14_CONSTEXPR 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
  503. operator>=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  504. {
  505. using default_ops::eval_lt;
  506. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  507. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  508. if (detail::is_unordered_comparison(t, t2))
  509. return false;
  510. return !eval_lt(t.backend(), t2.backend());
  511. }
  512. //
  513. // C99 comparison macros as functions:
  514. //
  515. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  516. inline BOOST_MP_CXX14_CONSTEXPR bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a > b; }
  517. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  518. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  519. isgreater
  520. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a > b; }
  521. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  522. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  523. isgreater
  524. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a > b; }
  525. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  526. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  527. isgreater
  528. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a > b; }
  529. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  530. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  531. isgreater
  532. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a > b; }
  533. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  534. inline BOOST_MP_CXX14_CONSTEXPR 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
  535. isgreater
  536. 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; }
  537. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  538. inline BOOST_MP_CXX14_CONSTEXPR bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a >= b; }
  539. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  540. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  541. isgreaterequal
  542. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a >= b; }
  543. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  544. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  545. isgreaterequal
  546. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a >= b; }
  547. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  548. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  549. isgreaterequal
  550. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a >= b; }
  551. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  552. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  553. isgreaterequal
  554. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a >= b; }
  555. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  556. inline BOOST_MP_CXX14_CONSTEXPR 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
  557. isgreaterequal
  558. 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; }
  559. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  560. inline BOOST_MP_CXX14_CONSTEXPR bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a <= b; }
  561. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  562. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  563. islessequal
  564. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a <= b; }
  565. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  566. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  567. islessequal
  568. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a <= b; }
  569. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  570. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  571. islessequal
  572. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a <= b; }
  573. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  574. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  575. islessequal
  576. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a <= b; }
  577. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  578. inline BOOST_MP_CXX14_CONSTEXPR 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
  579. islessequal
  580. 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; }
  581. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  582. inline BOOST_MP_CXX14_CONSTEXPR bool isless BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a < b; }
  583. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  584. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  585. isless
  586. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a < b; }
  587. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  588. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  589. isless
  590. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a < b; }
  591. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  592. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  593. isless
  594. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a < b; }
  595. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  596. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  597. isless
  598. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a < b; }
  599. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  600. inline BOOST_MP_CXX14_CONSTEXPR 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
  601. isless
  602. 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; }
  603. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  604. inline BOOST_MP_CXX14_CONSTEXPR bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  605. {
  606. if (detail::is_unordered_comparison(a, b))
  607. return false;
  608. return a != b;
  609. }
  610. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  611. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  612. islessgreater
  613. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  614. {
  615. if (detail::is_unordered_comparison(a, b))
  616. return false;
  617. return a != b;
  618. }
  619. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  620. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  621. islessgreater
  622. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  623. {
  624. if (detail::is_unordered_comparison(a, b))
  625. return false;
  626. return a != b;
  627. }
  628. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  629. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  630. islessgreater
  631. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
  632. {
  633. typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
  634. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  635. }
  636. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  637. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  638. islessgreater
  639. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
  640. {
  641. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  642. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  643. }
  644. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  645. inline BOOST_MP_CXX14_CONSTEXPR 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
  646. islessgreater
  647. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
  648. {
  649. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  650. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
  651. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  652. }
  653. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  654. inline BOOST_MP_CXX14_CONSTEXPR bool isunordered BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return detail::is_unordered_comparison(a, b); }
  655. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  656. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  657. isunordered
  658. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return detail::is_unordered_comparison(a, b); }
  659. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  660. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  661. isunordered
  662. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return detail::is_unordered_comparison(a, b); }
  663. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  664. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  665. isunordered
  666. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
  667. {
  668. typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
  669. return detail::is_unordered_comparison(a, b);
  670. }
  671. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  672. inline BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  673. isunordered
  674. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
  675. {
  676. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  677. return detail::is_unordered_comparison(a, b);
  678. }
  679. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  680. inline BOOST_MP_CXX14_CONSTEXPR 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
  681. isunordered
  682. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
  683. {
  684. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  685. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
  686. return detail::is_unordered_comparison(a, b);
  687. }
  688. }} // namespace boost::multiprecision
  689. #endif // BOOST_MP_COMPARE_HPP