number_compare.hpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  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 std::integral_constant<bool, 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 std::integral_constant<bool, 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. using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_first_backend<T, U>::value>;
  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 std::integral_constant<bool, 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 std::integral_constant<bool, 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. using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_first_backend<T, U>::value>;
  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 std::integral_constant<bool, 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 std::integral_constant<bool, 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. using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_first_backend<T, U>::value>;
  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 std::integral_constant<bool, false>
  91. {};
  92. template <class B, expression_template_option ET, class Val>
  93. struct is_valid_mixed_compare<number<B, ET>, Val> : public std::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 std::integral_constant<bool, 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 std::is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  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 std::is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  105. {};
  106. template <class Backend, expression_template_option ExpressionTemplates>
  107. inline constexpr typename std::enable_if<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. constexpr
  115. #endif
  116. typename std::enable_if<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 constexpr typename std::enable_if<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 std::enable_if < 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 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 std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && !is_number_expression<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 std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && !is_number_expression<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 std::enable_if<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. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::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 Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  190. inline BOOST_MP_CXX14_CONSTEXPR bool operator==(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  191. {
  192. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  193. using default_ops::eval_eq;
  194. result_type t(b);
  195. if (detail::is_unordered_comparison(a, t))
  196. return false;
  197. return eval_eq(t.backend(), a.backend());
  198. }
  199. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  200. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  201. operator==(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  202. {
  203. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  204. using default_ops::eval_eq;
  205. result_type t(a);
  206. if (detail::is_unordered_comparison(t, b))
  207. return false;
  208. return eval_eq(t.backend(), result_type::canonical_value(b));
  209. }
  210. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  211. inline BOOST_MP_CXX14_CONSTEXPR bool operator==(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  212. {
  213. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  214. using default_ops::eval_eq;
  215. result_type t(a);
  216. if (detail::is_unordered_comparison(t, b))
  217. return false;
  218. return eval_eq(t.backend(), b.backend());
  219. }
  220. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  221. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
  222. operator==(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  223. {
  224. using default_ops::eval_eq;
  225. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  226. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  227. if (detail::is_unordered_comparison(t, t2))
  228. return false;
  229. return eval_eq(t.backend(), t2.backend());
  230. }
  231. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  232. inline BOOST_MP_CXX14_CONSTEXPR bool operator!=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  233. {
  234. using default_ops::eval_eq;
  235. if (detail::is_unordered_comparison(a, b))
  236. return true;
  237. return !eval_eq(a.backend(), b.backend());
  238. }
  239. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  240. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && !is_number_expression<Arithmetic>::value, bool>::type
  241. operator!=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  242. {
  243. using default_ops::eval_eq;
  244. if (detail::is_unordered_comparison(a, b))
  245. return true;
  246. return !eval_eq(a.backend(), number<Backend, et_on>::canonical_value(b));
  247. }
  248. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  249. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && !is_number_expression<Arithmetic>::value, bool>::type
  250. operator!=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  251. {
  252. using default_ops::eval_eq;
  253. if (detail::is_unordered_comparison(a, b))
  254. return true;
  255. return !eval_eq(b.backend(), number<Backend, et_on>::canonical_value(a));
  256. }
  257. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  258. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  259. operator!=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  260. {
  261. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  262. using default_ops::eval_eq;
  263. result_type t(b);
  264. if (detail::is_unordered_comparison(a, t))
  265. return true;
  266. return !eval_eq(t.backend(), result_type::canonical_value(a));
  267. }
  268. template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  269. inline BOOST_MP_CXX14_CONSTEXPR bool operator!=(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  270. {
  271. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  272. using default_ops::eval_eq;
  273. result_type t(b);
  274. if (detail::is_unordered_comparison(a, t))
  275. return true;
  276. return !eval_eq(t.backend(), a.backend());
  277. }
  278. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  279. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  280. operator!=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  281. {
  282. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  283. using default_ops::eval_eq;
  284. result_type t(a);
  285. if (detail::is_unordered_comparison(t, b))
  286. return true;
  287. return !eval_eq(t.backend(), result_type::canonical_value(b));
  288. }
  289. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  290. inline BOOST_MP_CXX14_CONSTEXPR bool operator!=(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  291. {
  292. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  293. using default_ops::eval_eq;
  294. result_type t(a);
  295. if (detail::is_unordered_comparison(t, b))
  296. return true;
  297. return !eval_eq(t.backend(), result_type::canonical_value(b));
  298. }
  299. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  300. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
  301. operator!=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  302. {
  303. using default_ops::eval_eq;
  304. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  305. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  306. if (detail::is_unordered_comparison(t, t2))
  307. return true;
  308. return !eval_eq(t.backend(), t2.backend());
  309. }
  310. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  311. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  312. operator<(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  313. {
  314. using default_ops::eval_lt;
  315. if (detail::is_unordered_comparison(a, b))
  316. return false;
  317. return eval_lt(a.backend(), b.backend());
  318. }
  319. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  320. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
  321. operator<(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  322. {
  323. using default_ops::eval_lt;
  324. if (detail::is_unordered_comparison(a, b))
  325. return false;
  326. return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  327. }
  328. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  329. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
  330. operator<(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  331. {
  332. using default_ops::eval_gt;
  333. if (detail::is_unordered_comparison(a, b))
  334. return false;
  335. return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  336. }
  337. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  338. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
  339. operator<(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  340. {
  341. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  342. using default_ops::eval_gt;
  343. result_type t(b);
  344. if (detail::is_unordered_comparison(a, t))
  345. return false;
  346. return eval_gt(t.backend(), result_type::canonical_value(a));
  347. }
  348. template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  349. inline BOOST_MP_CXX14_CONSTEXPR bool operator<(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  350. {
  351. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  352. using default_ops::eval_gt;
  353. result_type t(b);
  354. return a < t;
  355. }
  356. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  357. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
  358. operator<(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  359. {
  360. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  361. using default_ops::eval_lt;
  362. result_type t(a);
  363. if (detail::is_unordered_comparison(t, b))
  364. return false;
  365. return eval_lt(t.backend(), result_type::canonical_value(b));
  366. }
  367. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  368. inline BOOST_MP_CXX14_CONSTEXPR bool operator<(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  369. {
  370. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  371. using default_ops::eval_lt;
  372. result_type t(a);
  373. return t < b;
  374. }
  375. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  376. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<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
  377. operator<(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  378. {
  379. using default_ops::eval_lt;
  380. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  381. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  382. if (detail::is_unordered_comparison(t, t2))
  383. return false;
  384. return eval_lt(t.backend(), t2.backend());
  385. }
  386. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  387. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  388. operator>(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  389. {
  390. using default_ops::eval_gt;
  391. if (detail::is_unordered_comparison(a, b))
  392. return false;
  393. return eval_gt(a.backend(), b.backend());
  394. }
  395. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  396. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
  397. operator>(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  398. {
  399. using default_ops::eval_gt;
  400. if (detail::is_unordered_comparison(a, b))
  401. return false;
  402. return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  403. }
  404. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  405. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
  406. operator>(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  407. {
  408. using default_ops::eval_lt;
  409. if (detail::is_unordered_comparison(a, b))
  410. return false;
  411. return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  412. }
  413. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  414. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
  415. operator>(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  416. {
  417. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  418. using default_ops::eval_lt;
  419. result_type t(b);
  420. return a > t;
  421. }
  422. template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  423. inline BOOST_MP_CXX14_CONSTEXPR bool operator>(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  424. {
  425. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  426. using default_ops::eval_lt;
  427. result_type t(b);
  428. return a > t;
  429. }
  430. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  431. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  435. using default_ops::eval_gt;
  436. result_type t(a);
  437. return t > b;
  438. }
  439. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  440. inline BOOST_MP_CXX14_CONSTEXPR bool operator>(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  441. {
  442. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  443. using default_ops::eval_gt;
  444. result_type t(a);
  445. return t > b;
  446. }
  447. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  448. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<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
  449. operator>(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  450. {
  451. using default_ops::eval_gt;
  452. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  453. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  454. return t > t2;
  455. }
  456. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  457. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  458. operator<=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  459. {
  460. using default_ops::eval_gt;
  461. if (detail::is_unordered_comparison(a, b))
  462. return false;
  463. return !eval_gt(a.backend(), b.backend());
  464. }
  465. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  466. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
  467. operator<=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  468. {
  469. using default_ops::eval_gt;
  470. if (detail::is_unordered_comparison(a, b))
  471. return false;
  472. return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  473. }
  474. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  475. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
  476. operator<=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  477. {
  478. using default_ops::eval_lt;
  479. if (detail::is_unordered_comparison(a, b))
  480. return false;
  481. return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  482. }
  483. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  484. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
  485. operator<=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  486. {
  487. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  488. using default_ops::eval_lt;
  489. if (detail::is_unordered_value(a) || detail::is_unordered_value(b))
  490. return false;
  491. result_type t(b);
  492. if (detail::is_unordered_comparison(a, t))
  493. return false;
  494. return !eval_lt(t.backend(), result_type::canonical_value(a));
  495. }
  496. template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  497. inline BOOST_MP_CXX14_CONSTEXPR bool operator<=(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  498. {
  499. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  500. using default_ops::eval_lt;
  501. if (detail::is_unordered_value(a) || detail::is_unordered_value(b))
  502. return false;
  503. result_type t(b);
  504. return a <= t;
  505. }
  506. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  507. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
  508. operator<=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  509. {
  510. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  511. using default_ops::eval_gt;
  512. result_type t(a);
  513. if (detail::is_unordered_comparison(t, b))
  514. return false;
  515. return !eval_gt(t.backend(), result_type::canonical_value(b));
  516. }
  517. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  518. inline BOOST_MP_CXX14_CONSTEXPR bool operator<=(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  519. {
  520. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  521. using default_ops::eval_gt;
  522. result_type t(a);
  523. return t <= b;
  524. }
  525. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  526. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<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
  527. operator<=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  528. {
  529. using default_ops::eval_gt;
  530. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  531. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  532. if (detail::is_unordered_comparison(t, t2))
  533. return false;
  534. return !eval_gt(t.backend(), t2.backend());
  535. }
  536. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  537. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(number_category<Backend>::value != number_kind_complex) && (number_category<Backend2>::value != number_kind_complex), bool>::type
  538. operator>=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  539. {
  540. using default_ops::eval_lt;
  541. if (detail::is_unordered_comparison(a, b))
  542. return false;
  543. return !eval_lt(a.backend(), b.backend());
  544. }
  545. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  546. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
  547. operator>=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  548. {
  549. using default_ops::eval_lt;
  550. if (detail::is_unordered_comparison(a, b))
  551. return false;
  552. return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  553. }
  554. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  555. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value && (number_category<Backend>::value != number_kind_complex) && !is_number_expression<Arithmetic>::value, bool>::type
  556. operator>=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  557. {
  558. using default_ops::eval_gt;
  559. if (detail::is_unordered_comparison(a, b))
  560. return false;
  561. return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  562. }
  563. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  564. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
  565. operator>=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  566. {
  567. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  568. using default_ops::eval_gt;
  569. result_type t(b);
  570. if (detail::is_unordered_comparison(a, t))
  571. return false;
  572. return !eval_gt(t.backend(), result_type::canonical_value(a));
  573. }
  574. template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  575. inline BOOST_MP_CXX14_CONSTEXPR bool operator>=(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  576. {
  577. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  578. using default_ops::eval_gt;
  579. result_type t(b);
  580. return a >= t;
  581. }
  582. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  583. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
  584. operator>=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  585. {
  586. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  587. using default_ops::eval_lt;
  588. result_type t(a);
  589. if (detail::is_unordered_comparison(t, b))
  590. return false;
  591. return !eval_lt(t.backend(), result_type::canonical_value(b));
  592. }
  593. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  594. inline BOOST_MP_CXX14_CONSTEXPR bool operator>=(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  595. {
  596. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  597. using default_ops::eval_lt;
  598. result_type t(a);
  599. return t >= b;
  600. }
  601. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  602. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<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
  603. operator>=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  604. {
  605. using default_ops::eval_lt;
  606. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  607. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  608. if (detail::is_unordered_comparison(t, t2))
  609. return false;
  610. return !eval_lt(t.backend(), t2.backend());
  611. }
  612. //
  613. // C99 comparison macros as functions:
  614. //
  615. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  616. inline BOOST_MP_CXX14_CONSTEXPR bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a > b; }
  617. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  618. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  619. isgreater
  620. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a > b; }
  621. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  622. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  623. isgreater
  624. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a > b; }
  625. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  626. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  627. isgreater
  628. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a > b; }
  629. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  630. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  631. isgreater
  632. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a > b; }
  633. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  634. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
  635. isgreater
  636. 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; }
  637. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  638. inline BOOST_MP_CXX14_CONSTEXPR bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a >= b; }
  639. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  640. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  641. isgreaterequal
  642. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a >= b; }
  643. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  644. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  645. isgreaterequal
  646. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a >= b; }
  647. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  648. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  649. isgreaterequal
  650. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a >= b; }
  651. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  652. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  653. isgreaterequal
  654. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a >= b; }
  655. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  656. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
  657. isgreaterequal
  658. 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; }
  659. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  660. inline BOOST_MP_CXX14_CONSTEXPR bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a <= b; }
  661. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  662. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  663. islessequal
  664. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a <= b; }
  665. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  666. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  667. islessequal
  668. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a <= b; }
  669. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  670. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  671. islessequal
  672. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a <= b; }
  673. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  674. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  675. islessequal
  676. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a <= b; }
  677. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  678. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
  679. islessequal
  680. 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; }
  681. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  682. inline BOOST_MP_CXX14_CONSTEXPR bool isless BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a < b; }
  683. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  684. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  685. isless
  686. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a < b; }
  687. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  688. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  689. isless
  690. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a < b; }
  691. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  692. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  693. isless
  694. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a < b; }
  695. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  696. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  697. isless
  698. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a < b; }
  699. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  700. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
  701. isless
  702. 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; }
  703. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  704. inline BOOST_MP_CXX14_CONSTEXPR bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  705. {
  706. if (detail::is_unordered_comparison(a, b))
  707. return false;
  708. return a != b;
  709. }
  710. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  711. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  712. islessgreater
  713. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  714. {
  715. if (detail::is_unordered_comparison(a, b))
  716. return false;
  717. return a != b;
  718. }
  719. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  720. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  721. islessgreater
  722. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  723. {
  724. if (detail::is_unordered_comparison(a, b))
  725. return false;
  726. return a != b;
  727. }
  728. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  729. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  730. islessgreater
  731. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
  732. {
  733. typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
  734. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  735. }
  736. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  737. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  738. islessgreater
  739. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
  740. {
  741. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  742. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  743. }
  744. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  745. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
  746. islessgreater
  747. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
  748. {
  749. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  750. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
  751. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  752. }
  753. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  754. 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); }
  755. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  756. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  757. isunordered
  758. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return detail::is_unordered_comparison(a, b); }
  759. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  760. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  761. isunordered
  762. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return detail::is_unordered_comparison(a, b); }
  763. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  764. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  765. isunordered
  766. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
  767. {
  768. typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
  769. return detail::is_unordered_comparison(a, b);
  770. }
  771. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  772. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
  773. isunordered
  774. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
  775. {
  776. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  777. return detail::is_unordered_comparison(a, b);
  778. }
  779. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  780. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_equivalent_number_type<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>::value, bool>::type
  781. isunordered
  782. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
  783. {
  784. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  785. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
  786. return detail::is_unordered_comparison(a, b);
  787. }
  788. }} // namespace boost::multiprecision
  789. #endif // BOOST_MP_COMPARE_HPP