number_compare.hpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  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_NUMBER_COMPARE_HPP
  6. #define BOOST_MP_NUMBER_COMPARE_HPP
  7. #include <boost/multiprecision/traits/is_backend.hpp>
  8. #include <boost/multiprecision/detail/fpclassify.hpp>
  9. //
  10. // Comparison operators for number.
  11. //
  12. namespace boost { namespace multiprecision {
  13. namespace default_ops {
  14. //
  15. // The dispatching mechanism used here to deal with differently typed arguments
  16. // could be better replaced with enable_if overloads, but that breaks MSVC-12
  17. // under strange and hard to reproduce circumstances.
  18. //
  19. template <class B>
  20. inline BOOST_MP_CXX14_CONSTEXPR bool eval_eq(const B& a, const B& b)
  21. {
  22. return a.compare(b) == 0;
  23. }
  24. template <class T, class U>
  25. inline BOOST_MP_CXX14_CONSTEXPR bool eval_eq_imp(const T& a, const U& b, const std::integral_constant<bool, true>&)
  26. {
  27. typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
  28. return eval_eq(a, t.backend());
  29. }
  30. template <class T, class U>
  31. inline BOOST_MP_CXX14_CONSTEXPR bool eval_eq_imp(const T& a, const U& b, const std::integral_constant<bool, false>&)
  32. {
  33. typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
  34. return eval_eq(t.backend(), b);
  35. }
  36. template <class T, class U>
  37. inline BOOST_MP_CXX14_CONSTEXPR bool eval_eq(const T& a, const U& b)
  38. {
  39. using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_first_backend<T, U>::value>;
  40. return eval_eq_imp(a, b, tag_type());
  41. }
  42. template <class B>
  43. inline BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const B& a, const B& b)
  44. {
  45. return a.compare(b) < 0;
  46. }
  47. template <class T, class U>
  48. inline BOOST_MP_CXX14_CONSTEXPR bool eval_lt_imp(const T& a, const U& b, const std::integral_constant<bool, true>&)
  49. {
  50. typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
  51. return eval_lt(a, t.backend());
  52. }
  53. template <class T, class U>
  54. inline BOOST_MP_CXX14_CONSTEXPR bool eval_lt_imp(const T& a, const U& b, const std::integral_constant<bool, false>&)
  55. {
  56. typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
  57. return eval_lt(t.backend(), b);
  58. }
  59. template <class T, class U>
  60. inline BOOST_MP_CXX14_CONSTEXPR bool eval_lt(const T& a, const U& b)
  61. {
  62. using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_first_backend<T, U>::value>;
  63. return eval_lt_imp(a, b, tag_type());
  64. }
  65. template <class B>
  66. inline BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const B& a, const B& b)
  67. {
  68. return a.compare(b) > 0;
  69. }
  70. template <class T, class U>
  71. inline BOOST_MP_CXX14_CONSTEXPR bool eval_gt_imp(const T& a, const U& b, const std::integral_constant<bool, true>&)
  72. {
  73. typename boost::multiprecision::detail::number_from_backend<T, U>::type t(b);
  74. return eval_gt(a, t.backend());
  75. }
  76. template <class T, class U>
  77. inline BOOST_MP_CXX14_CONSTEXPR bool eval_gt_imp(const T& a, const U& b, const std::integral_constant<bool, false>&)
  78. {
  79. typename boost::multiprecision::detail::number_from_backend<U, T>::type t(a);
  80. return eval_gt(t.backend(), b);
  81. }
  82. template <class T, class U>
  83. inline BOOST_MP_CXX14_CONSTEXPR bool eval_gt(const T& a, const U& b)
  84. {
  85. using tag_type = std::integral_constant<bool, boost::multiprecision::detail::is_first_backend<T, U>::value>;
  86. return eval_gt_imp(a, b, tag_type());
  87. }
  88. } // namespace default_ops
  89. namespace detail {
  90. template <class Num, class Val>
  91. struct is_valid_mixed_compare : public std::integral_constant<bool, false>
  92. {};
  93. template <class B, expression_template_option ET, class Val>
  94. struct is_valid_mixed_compare<number<B, ET>, Val> : public std::is_convertible<Val, number<B, ET> >
  95. {};
  96. template <class B, expression_template_option ET>
  97. struct is_valid_mixed_compare<number<B, ET>, number<B, ET> > : public std::integral_constant<bool, false>
  98. {};
  99. template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
  100. struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> >
  101. : public std::is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  102. {};
  103. template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
  104. struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  105. : public std::is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
  106. {};
  107. template <class Backend, expression_template_option ExpressionTemplates>
  108. inline constexpr typename std::enable_if<number_category<Backend>::value != number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>&)
  109. {
  110. return false;
  111. }
  112. template <class Backend, expression_template_option ExpressionTemplates>
  113. inline constexpr typename std::enable_if<number_category<Backend>::value == number_kind_floating_point, bool>::type is_unordered_value(const number<Backend, ExpressionTemplates>& a)
  114. {
  115. using default_ops::eval_fpclassify;
  116. return eval_fpclassify(a.backend()) == FP_NAN;
  117. }
  118. template <class Arithmetic>
  119. inline constexpr typename std::enable_if<number_category<Arithmetic>::value != number_kind_floating_point, bool>::type is_unordered_value(const Arithmetic&)
  120. {
  121. return false;
  122. }
  123. template <class Arithmetic>
  124. inline
  125. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  126. BOOST_MP_CXX14_CONSTEXPR
  127. #endif
  128. typename std::enable_if < number_category < Arithmetic> ::value == number_kind_floating_point, bool> ::type
  129. is_unordered_value(const Arithmetic& a)
  130. {
  131. #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
  132. if (BOOST_MP_IS_CONST_EVALUATED(a))
  133. {
  134. return a != a;
  135. }
  136. else
  137. #endif
  138. {
  139. return BOOST_MP_ISNAN(a);
  140. }
  141. }
  142. template <class T, class U>
  143. inline constexpr bool is_unordered_comparison(const T& a, const U& b)
  144. {
  145. return is_unordered_value(a) || is_unordered_value(b);
  146. }
  147. } // namespace detail
  148. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  149. inline BOOST_MP_CXX14_CONSTEXPR bool operator==(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  150. {
  151. using default_ops::eval_eq;
  152. if (detail::is_unordered_comparison(a, b))
  153. return false;
  154. return eval_eq(a.backend(), b.backend());
  155. }
  156. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  157. 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
  158. operator==(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  159. {
  160. using default_ops::eval_eq;
  161. if (detail::is_unordered_comparison(a, b))
  162. return false;
  163. return eval_eq(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  164. }
  165. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  166. 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
  167. operator==(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  168. {
  169. using default_ops::eval_eq;
  170. if (detail::is_unordered_comparison(a, b))
  171. return false;
  172. return eval_eq(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  173. }
  174. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  175. 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
  176. operator==(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  177. {
  178. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  179. using default_ops::eval_eq;
  180. result_type t(b);
  181. if (detail::is_unordered_comparison(a, t))
  182. return false;
  183. return eval_eq(t.backend(), result_type::canonical_value(a));
  184. }
  185. template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  186. inline BOOST_MP_CXX14_CONSTEXPR bool operator==(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  187. {
  188. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  189. using default_ops::eval_eq;
  190. result_type t(b);
  191. if (detail::is_unordered_comparison(a, t))
  192. return false;
  193. return eval_eq(t.backend(), a.backend());
  194. }
  195. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  196. 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
  197. operator==(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  198. {
  199. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  200. using default_ops::eval_eq;
  201. result_type t(a);
  202. if (detail::is_unordered_comparison(t, b))
  203. return false;
  204. return eval_eq(t.backend(), result_type::canonical_value(b));
  205. }
  206. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  207. inline BOOST_MP_CXX14_CONSTEXPR bool operator==(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  208. {
  209. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  210. using default_ops::eval_eq;
  211. result_type t(a);
  212. if (detail::is_unordered_comparison(t, b))
  213. return false;
  214. return eval_eq(t.backend(), b.backend());
  215. }
  216. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  217. 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
  218. operator==(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  219. {
  220. using default_ops::eval_eq;
  221. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  222. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  223. if (detail::is_unordered_comparison(t, t2))
  224. return false;
  225. return eval_eq(t.backend(), t2.backend());
  226. }
  227. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  228. inline BOOST_MP_CXX14_CONSTEXPR bool operator!=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  229. {
  230. using default_ops::eval_eq;
  231. if (detail::is_unordered_comparison(a, b))
  232. return true;
  233. return !eval_eq(a.backend(), b.backend());
  234. }
  235. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  236. 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
  237. operator!=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  238. {
  239. using default_ops::eval_eq;
  240. if (detail::is_unordered_comparison(a, b))
  241. return true;
  242. return !eval_eq(a.backend(), number<Backend, et_on>::canonical_value(b));
  243. }
  244. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  245. 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
  246. operator!=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  247. {
  248. using default_ops::eval_eq;
  249. if (detail::is_unordered_comparison(a, b))
  250. return true;
  251. return !eval_eq(b.backend(), number<Backend, et_on>::canonical_value(a));
  252. }
  253. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  254. 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
  255. operator!=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  256. {
  257. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  258. using default_ops::eval_eq;
  259. result_type t(b);
  260. if (detail::is_unordered_comparison(a, t))
  261. return true;
  262. return !eval_eq(t.backend(), result_type::canonical_value(a));
  263. }
  264. template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  265. inline BOOST_MP_CXX14_CONSTEXPR bool operator!=(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  266. {
  267. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  268. using default_ops::eval_eq;
  269. result_type t(b);
  270. if (detail::is_unordered_comparison(a, t))
  271. return true;
  272. return !eval_eq(t.backend(), a.backend());
  273. }
  274. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  275. 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
  276. operator!=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  277. {
  278. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  279. using default_ops::eval_eq;
  280. result_type t(a);
  281. if (detail::is_unordered_comparison(t, b))
  282. return true;
  283. return !eval_eq(t.backend(), result_type::canonical_value(b));
  284. }
  285. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  286. inline BOOST_MP_CXX14_CONSTEXPR bool operator!=(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  287. {
  288. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  289. using default_ops::eval_eq;
  290. result_type t(a);
  291. if (detail::is_unordered_comparison(t, b))
  292. return true;
  293. return !eval_eq(t.backend(), result_type::canonical_value(b));
  294. }
  295. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  296. 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
  297. operator!=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  298. {
  299. using default_ops::eval_eq;
  300. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  301. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  302. if (detail::is_unordered_comparison(t, t2))
  303. return true;
  304. return !eval_eq(t.backend(), t2.backend());
  305. }
  306. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  307. 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
  308. operator<(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  309. {
  310. using default_ops::eval_lt;
  311. if (detail::is_unordered_comparison(a, b))
  312. return false;
  313. return eval_lt(a.backend(), b.backend());
  314. }
  315. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  316. 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
  317. operator<(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  318. {
  319. using default_ops::eval_lt;
  320. if (detail::is_unordered_comparison(a, b))
  321. return false;
  322. return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  323. }
  324. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  325. 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
  326. operator<(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  327. {
  328. using default_ops::eval_gt;
  329. if (detail::is_unordered_comparison(a, b))
  330. return false;
  331. return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  332. }
  333. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  334. inline 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
  335. operator<(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  336. {
  337. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  338. using default_ops::eval_gt;
  339. result_type t(b);
  340. if (detail::is_unordered_comparison(a, t))
  341. return false;
  342. return eval_gt(t.backend(), result_type::canonical_value(a));
  343. }
  344. template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  345. inline BOOST_MP_CXX14_CONSTEXPR bool operator<(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  346. {
  347. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  348. using default_ops::eval_gt;
  349. result_type t(b);
  350. return a < t;
  351. }
  352. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  353. 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
  354. operator<(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  355. {
  356. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  357. using default_ops::eval_lt;
  358. result_type t(a);
  359. if (detail::is_unordered_comparison(t, b))
  360. return false;
  361. return eval_lt(t.backend(), result_type::canonical_value(b));
  362. }
  363. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  364. inline BOOST_MP_CXX14_CONSTEXPR bool operator<(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  365. {
  366. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  367. using default_ops::eval_lt;
  368. result_type t(a);
  369. return t < b;
  370. }
  371. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  372. 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
  373. operator<(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  374. {
  375. using default_ops::eval_lt;
  376. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  377. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  378. if (detail::is_unordered_comparison(t, t2))
  379. return false;
  380. return eval_lt(t.backend(), t2.backend());
  381. }
  382. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  383. 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
  384. operator>(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  385. {
  386. using default_ops::eval_gt;
  387. if (detail::is_unordered_comparison(a, b))
  388. return false;
  389. return eval_gt(a.backend(), b.backend());
  390. }
  391. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  392. 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
  393. operator>(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  394. {
  395. using default_ops::eval_gt;
  396. if (detail::is_unordered_comparison(a, b))
  397. return false;
  398. return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  399. }
  400. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  401. 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
  402. operator>(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  403. {
  404. using default_ops::eval_lt;
  405. if (detail::is_unordered_comparison(a, b))
  406. return false;
  407. return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  408. }
  409. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  410. 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
  411. operator>(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  412. {
  413. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  414. using default_ops::eval_lt;
  415. result_type t(b);
  416. return a > t;
  417. }
  418. template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  419. inline BOOST_MP_CXX14_CONSTEXPR bool operator>(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  420. {
  421. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  422. using default_ops::eval_lt;
  423. result_type t(b);
  424. return a > t;
  425. }
  426. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  427. 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
  428. operator>(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  429. {
  430. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  431. using default_ops::eval_gt;
  432. result_type t(a);
  433. return t > b;
  434. }
  435. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  436. inline BOOST_MP_CXX14_CONSTEXPR bool operator>(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  437. {
  438. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  439. using default_ops::eval_gt;
  440. result_type t(a);
  441. return t > b;
  442. }
  443. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  444. 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
  445. operator>(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  446. {
  447. using default_ops::eval_gt;
  448. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  449. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  450. return t > t2;
  451. }
  452. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  453. 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
  454. operator<=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  455. {
  456. using default_ops::eval_gt;
  457. if (detail::is_unordered_comparison(a, b))
  458. return false;
  459. return !eval_gt(a.backend(), b.backend());
  460. }
  461. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  462. 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
  463. operator<=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  464. {
  465. using default_ops::eval_gt;
  466. if (detail::is_unordered_comparison(a, b))
  467. return false;
  468. return !eval_gt(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 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
  472. operator<=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  473. {
  474. using default_ops::eval_lt;
  475. if (detail::is_unordered_comparison(a, b))
  476. return false;
  477. return !eval_lt(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 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
  481. operator<=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  482. {
  483. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  484. using default_ops::eval_lt;
  485. if (detail::is_unordered_value(a) || detail::is_unordered_value(b))
  486. return false;
  487. result_type t(b);
  488. if (detail::is_unordered_comparison(a, t))
  489. return false;
  490. return !eval_lt(t.backend(), result_type::canonical_value(a));
  491. }
  492. template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  493. inline BOOST_MP_CXX14_CONSTEXPR bool operator<=(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  494. {
  495. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  496. using default_ops::eval_lt;
  497. if (detail::is_unordered_value(a) || detail::is_unordered_value(b))
  498. return false;
  499. result_type t(b);
  500. return a <= t;
  501. }
  502. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  503. 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
  504. operator<=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  505. {
  506. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  507. using default_ops::eval_gt;
  508. result_type t(a);
  509. if (detail::is_unordered_comparison(t, b))
  510. return false;
  511. return !eval_gt(t.backend(), result_type::canonical_value(b));
  512. }
  513. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  514. inline BOOST_MP_CXX14_CONSTEXPR bool operator<=(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  515. {
  516. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  517. using default_ops::eval_gt;
  518. result_type t(a);
  519. return t <= b;
  520. }
  521. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  522. 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
  523. operator<=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  524. {
  525. using default_ops::eval_gt;
  526. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  527. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  528. if (detail::is_unordered_comparison(t, t2))
  529. return false;
  530. return !eval_gt(t.backend(), t2.backend());
  531. }
  532. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  533. 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
  534. operator>=(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  535. {
  536. using default_ops::eval_lt;
  537. if (detail::is_unordered_comparison(a, b))
  538. return false;
  539. return !eval_lt(a.backend(), b.backend());
  540. }
  541. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  542. 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
  543. operator>=(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  544. {
  545. using default_ops::eval_lt;
  546. if (detail::is_unordered_comparison(a, b))
  547. return false;
  548. return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
  549. }
  550. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  551. 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
  552. operator>=(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  553. {
  554. using default_ops::eval_gt;
  555. if (detail::is_unordered_comparison(a, b))
  556. return false;
  557. return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
  558. }
  559. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  560. 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
  561. operator>=(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  562. {
  563. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  564. using default_ops::eval_gt;
  565. result_type t(b);
  566. if (detail::is_unordered_comparison(a, t))
  567. return false;
  568. return !eval_gt(t.backend(), result_type::canonical_value(a));
  569. }
  570. template <class Backend, expression_template_option ExpressionTemplates, class Tag, class A1, class A2, class A3, class A4>
  571. inline BOOST_MP_CXX14_CONSTEXPR bool operator>=(const number<Backend, ExpressionTemplates>& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
  572. {
  573. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  574. using default_ops::eval_gt;
  575. result_type t(b);
  576. return a >= t;
  577. }
  578. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  579. 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
  580. operator>=(const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
  581. {
  582. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  583. using default_ops::eval_lt;
  584. result_type t(a);
  585. if (detail::is_unordered_comparison(t, b))
  586. return false;
  587. return !eval_lt(t.backend(), result_type::canonical_value(b));
  588. }
  589. template <class Tag, class A1, class A2, class A3, class A4, class Backend, expression_template_option ExpressionTemplates>
  590. inline BOOST_MP_CXX14_CONSTEXPR bool operator>=(const detail::expression<Tag, A1, A2, A3, A4>& a, const number<Backend, ExpressionTemplates>& b)
  591. {
  592. using result_type = typename detail::expression<Tag, A1, A2, A3, A4>::result_type;
  593. using default_ops::eval_lt;
  594. result_type t(a);
  595. return t >= b;
  596. }
  597. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  598. 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
  599. operator>=(const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
  600. {
  601. using default_ops::eval_lt;
  602. typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
  603. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
  604. if (detail::is_unordered_comparison(t, t2))
  605. return false;
  606. return !eval_lt(t.backend(), t2.backend());
  607. }
  608. //
  609. // C99 comparison macros as functions:
  610. //
  611. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  612. inline BOOST_MP_CXX14_CONSTEXPR bool isgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a > b; }
  613. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  614. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  615. isgreater
  616. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a > b; }
  617. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  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 Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a > b; }
  621. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  622. 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
  623. isgreater
  624. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a > b; }
  625. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  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 detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a > b; }
  629. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  630. 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
  631. isgreater
  632. 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; }
  633. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  634. inline BOOST_MP_CXX14_CONSTEXPR bool isgreaterequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a >= b; }
  635. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  636. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  637. isgreaterequal
  638. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a >= b; }
  639. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  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 Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a >= b; }
  643. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  644. 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
  645. isgreaterequal
  646. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a >= b; }
  647. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  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 detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a >= b; }
  651. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  652. 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
  653. isgreaterequal
  654. 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; }
  655. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  656. inline BOOST_MP_CXX14_CONSTEXPR bool islessequal BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a <= b; }
  657. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  658. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  659. islessequal
  660. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a <= b; }
  661. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  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 Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a <= b; }
  665. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  666. 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
  667. islessequal
  668. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a <= b; }
  669. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  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 detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a <= b; }
  673. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  674. 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
  675. islessequal
  676. 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; }
  677. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  678. inline BOOST_MP_CXX14_CONSTEXPR bool isless BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b) { return a < b; }
  679. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  680. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  681. isless
  682. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return a < b; }
  683. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  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 Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return a < b; }
  687. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  688. 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
  689. isless
  690. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b) { return a < b; }
  691. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  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 detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b) { return a < b; }
  695. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  696. 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
  697. isless
  698. 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; }
  699. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  700. inline BOOST_MP_CXX14_CONSTEXPR bool islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const number<Backend2, ExpressionTemplates2>& b)
  701. {
  702. if (detail::is_unordered_comparison(a, b))
  703. return false;
  704. return a != b;
  705. }
  706. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  707. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  708. islessgreater
  709. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
  710. {
  711. if (detail::is_unordered_comparison(a, b))
  712. return false;
  713. return a != b;
  714. }
  715. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  716. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  717. islessgreater
  718. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
  719. {
  720. if (detail::is_unordered_comparison(a, b))
  721. return false;
  722. return a != b;
  723. }
  724. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  725. 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
  726. islessgreater
  727. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
  728. {
  729. typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
  730. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  731. }
  732. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  733. 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
  734. islessgreater
  735. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
  736. {
  737. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  738. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  739. }
  740. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  741. 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
  742. islessgreater
  743. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
  744. {
  745. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  746. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
  747. return islessgreater BOOST_PREVENT_MACRO_SUBSTITUTION(a, b);
  748. }
  749. template <class Backend, expression_template_option ExpressionTemplates, class Backend2, expression_template_option ExpressionTemplates2>
  750. 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); }
  751. template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
  752. inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
  753. isunordered
  754. BOOST_PREVENT_MACRO_SUBSTITUTION(const number<Backend, ExpressionTemplates>& a, const Arithmetic& b) { return detail::is_unordered_comparison(a, b); }
  755. template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
  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 Arithmetic& a, const number<Backend, ExpressionTemplates>& b) { return detail::is_unordered_comparison(a, b); }
  759. template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
  760. 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
  761. isunordered
  762. BOOST_PREVENT_MACRO_SUBSTITUTION(const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& bb)
  763. {
  764. typename detail::expression<Tag, A1, A2, A3, A4>::result_type b(bb);
  765. return detail::is_unordered_comparison(a, b);
  766. }
  767. template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
  768. 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
  769. isunordered
  770. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const Arithmetic& b)
  771. {
  772. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  773. return detail::is_unordered_comparison(a, b);
  774. }
  775. template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
  776. 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
  777. isunordered
  778. BOOST_PREVENT_MACRO_SUBSTITUTION(const detail::expression<Tag, A1, A2, A3, A4>& aa, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& bb)
  779. {
  780. typename detail::expression<Tag, A1, A2, A3, A4>::result_type a(aa);
  781. typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type b(bb);
  782. return detail::is_unordered_comparison(a, b);
  783. }
  784. }} // namespace boost::multiprecision
  785. #endif // BOOST_MP_NUMBER_COMPARE_HPP