utility.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /* Boost interval/utility.hpp template implementation file
  2. *
  3. * Copyright 2000 Jens Maurer
  4. * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
  5. *
  6. * Distributed under the Boost Software License, Version 1.0.
  7. * (See accompanying file LICENSE_1_0.txt or
  8. * copy at http://www.boost.org/LICENSE_1_0.txt)
  9. */
  10. #ifndef BOOST_NUMERIC_INTERVAL_UTILITY_HPP
  11. #define BOOST_NUMERIC_INTERVAL_UTILITY_HPP
  12. #include <boost/numeric/interval/utility_fwd.hpp>
  13. #include <boost/numeric/interval/detail/test_input.hpp>
  14. #include <boost/numeric/interval/detail/bugs.hpp>
  15. #include <algorithm>
  16. #include <utility>
  17. /*
  18. * Implementation of simple functions
  19. */
  20. namespace boost {
  21. namespace numeric {
  22. /*
  23. * Utility Functions
  24. */
  25. template<class T, class Policies> inline
  26. const T& lower(const interval<T, Policies>& x)
  27. {
  28. return x.lower();
  29. }
  30. template<class T, class Policies> inline
  31. const T& upper(const interval<T, Policies>& x)
  32. {
  33. return x.upper();
  34. }
  35. template<class T, class Policies> inline
  36. T checked_lower(const interval<T, Policies>& x)
  37. {
  38. if (empty(x)) {
  39. typedef typename Policies::checking checking;
  40. return checking::nan();
  41. }
  42. return x.lower();
  43. }
  44. template<class T, class Policies> inline
  45. T checked_upper(const interval<T, Policies>& x)
  46. {
  47. if (empty(x)) {
  48. typedef typename Policies::checking checking;
  49. return checking::nan();
  50. }
  51. return x.upper();
  52. }
  53. template<class T, class Policies> inline
  54. T width(const interval<T, Policies>& x)
  55. {
  56. if (interval_lib::detail::test_input(x)) return static_cast<T>(0);
  57. typename Policies::rounding rnd;
  58. return rnd.sub_up(x.upper(), x.lower());
  59. }
  60. template<class T, class Policies> inline
  61. T median(const interval<T, Policies>& x)
  62. {
  63. if (interval_lib::detail::test_input(x)) {
  64. typedef typename Policies::checking checking;
  65. return checking::nan();
  66. }
  67. typename Policies::rounding rnd;
  68. return rnd.median(x.lower(), x.upper());
  69. }
  70. template<class T, class Policies> inline
  71. interval<T, Policies> widen(const interval<T, Policies>& x, const T& v)
  72. {
  73. if (interval_lib::detail::test_input(x))
  74. return interval<T, Policies>::empty();
  75. typename Policies::rounding rnd;
  76. return interval<T, Policies>(rnd.sub_down(x.lower(), v),
  77. rnd.add_up (x.upper(), v), true);
  78. }
  79. /*
  80. * Set-like operations
  81. */
  82. template<class T, class Policies> inline
  83. bool empty(const interval<T, Policies>& x)
  84. {
  85. return interval_lib::detail::test_input(x);
  86. }
  87. template<class T, class Policies> inline
  88. bool zero_in(const interval<T, Policies>& x)
  89. {
  90. if (interval_lib::detail::test_input(x)) return false;
  91. return (!interval_lib::user::is_pos(x.lower())) &&
  92. (!interval_lib::user::is_neg(x.upper()));
  93. }
  94. template<class T, class Policies> inline
  95. bool in_zero(const interval<T, Policies>& x) // DEPRECATED
  96. {
  97. return zero_in<T, Policies>(x);
  98. }
  99. template<class T, class Policies> inline
  100. bool in(const T& x, const interval<T, Policies>& y)
  101. {
  102. if (interval_lib::detail::test_input(x, y)) return false;
  103. return y.lower() <= x && x <= y.upper();
  104. }
  105. template<class T, class Policies> inline
  106. bool subset(const interval<T, Policies>& x,
  107. const interval<T, Policies>& y)
  108. {
  109. if (empty(x)) return true;
  110. return !empty(y) && y.lower() <= x.lower() && x.upper() <= y.upper();
  111. }
  112. template<class T, class Policies1, class Policies2> inline
  113. bool proper_subset(const interval<T, Policies1>& x,
  114. const interval<T, Policies2>& y)
  115. {
  116. if (empty(y)) return false;
  117. if (empty(x)) return true;
  118. return y.lower() <= x.lower() && x.upper() <= y.upper() &&
  119. (y.lower() != x.lower() || x.upper() != y.upper());
  120. }
  121. template<class T, class Policies1, class Policies2> inline
  122. bool overlap(const interval<T, Policies1>& x,
  123. const interval<T, Policies2>& y)
  124. {
  125. if (interval_lib::detail::test_input(x, y)) return false;
  126. return (x.lower() <= y.lower() && y.lower() <= x.upper()) ||
  127. (y.lower() <= x.lower() && x.lower() <= y.upper());
  128. }
  129. template<class T, class Policies> inline
  130. bool singleton(const interval<T, Policies>& x)
  131. {
  132. return !empty(x) && x.lower() == x.upper();
  133. }
  134. template<class T, class Policies1, class Policies2> inline
  135. bool equal(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
  136. {
  137. if (empty(x)) return empty(y);
  138. return !empty(y) && x.lower() == y.lower() && x.upper() == y.upper();
  139. }
  140. template<class T, class Policies> inline
  141. interval<T, Policies> intersect(const interval<T, Policies>& x,
  142. const interval<T, Policies>& y)
  143. {
  144. BOOST_USING_STD_MIN();
  145. BOOST_USING_STD_MAX();
  146. if (interval_lib::detail::test_input(x, y))
  147. return interval<T, Policies>::empty();
  148. const T& l = max BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower());
  149. const T& u = min BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper());
  150. if (l <= u) return interval<T, Policies>(l, u, true);
  151. else return interval<T, Policies>::empty();
  152. }
  153. template<class T, class Policies> inline
  154. interval<T, Policies> hull(const interval<T, Policies>& x,
  155. const interval<T, Policies>& y)
  156. {
  157. BOOST_USING_STD_MIN();
  158. BOOST_USING_STD_MAX();
  159. bool bad_x = interval_lib::detail::test_input(x);
  160. bool bad_y = interval_lib::detail::test_input(y);
  161. if (bad_x)
  162. if (bad_y) return interval<T, Policies>::empty();
  163. else return y;
  164. else
  165. if (bad_y) return x;
  166. return interval<T, Policies>(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower()),
  167. max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper()), true);
  168. }
  169. template<class T, class Policies> inline
  170. interval<T, Policies> hull(const interval<T, Policies>& x, const T& y)
  171. {
  172. BOOST_USING_STD_MIN();
  173. BOOST_USING_STD_MAX();
  174. bool bad_x = interval_lib::detail::test_input(x);
  175. bool bad_y = interval_lib::detail::test_input<T, Policies>(y);
  176. if (bad_y)
  177. if (bad_x) return interval<T, Policies>::empty();
  178. else return x;
  179. else
  180. if (bad_x) return interval<T, Policies>(y, y, true);
  181. return interval<T, Policies>(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y),
  182. max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y), true);
  183. }
  184. template<class T, class Policies> inline
  185. interval<T, Policies> hull(const T& x, const interval<T, Policies>& y)
  186. {
  187. BOOST_USING_STD_MIN();
  188. BOOST_USING_STD_MAX();
  189. bool bad_x = interval_lib::detail::test_input<T, Policies>(x);
  190. bool bad_y = interval_lib::detail::test_input(y);
  191. if (bad_x)
  192. if (bad_y) return interval<T, Policies>::empty();
  193. else return y;
  194. else
  195. if (bad_y) return interval<T, Policies>(x, x, true);
  196. return interval<T, Policies>(min BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.lower()),
  197. max BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.upper()), true);
  198. }
  199. template<class T> inline
  200. interval<T> hull(const T& x, const T& y)
  201. {
  202. return interval<T>::hull(x, y);
  203. }
  204. template<class T, class Policies> inline
  205. std::pair<interval<T, Policies>, interval<T, Policies> >
  206. bisect(const interval<T, Policies>& x)
  207. {
  208. typedef interval<T, Policies> I;
  209. if (interval_lib::detail::test_input(x))
  210. return std::pair<I,I>(I::empty(), I::empty());
  211. const T m = median(x);
  212. return std::pair<I,I>(I(x.lower(), m, true), I(m, x.upper(), true));
  213. }
  214. /*
  215. * Elementary functions
  216. */
  217. template<class T, class Policies> inline
  218. T norm(const interval<T, Policies>& x)
  219. {
  220. if (interval_lib::detail::test_input(x)) {
  221. typedef typename Policies::checking checking;
  222. return checking::nan();
  223. }
  224. BOOST_USING_STD_MAX();
  225. return max BOOST_PREVENT_MACRO_SUBSTITUTION(static_cast<T>(-x.lower()), x.upper());
  226. }
  227. template<class T, class Policies> inline
  228. interval<T, Policies> abs(const interval<T, Policies>& x)
  229. {
  230. typedef interval<T, Policies> I;
  231. if (interval_lib::detail::test_input(x))
  232. return I::empty();
  233. if (!interval_lib::user::is_neg(x.lower())) return x;
  234. if (!interval_lib::user::is_pos(x.upper())) return -x;
  235. BOOST_USING_STD_MAX();
  236. return I(static_cast<T>(0), max BOOST_PREVENT_MACRO_SUBSTITUTION(static_cast<T>(-x.lower()), x.upper()), true);
  237. }
  238. template<class T, class Policies> inline
  239. interval<T, Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x,
  240. const interval<T, Policies>& y)
  241. {
  242. typedef interval<T, Policies> I;
  243. if (interval_lib::detail::test_input(x, y))
  244. return I::empty();
  245. BOOST_USING_STD_MAX();
  246. return I(max BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower()), max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper()), true);
  247. }
  248. template<class T, class Policies> inline
  249. interval<T, Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x, const T& y)
  250. {
  251. typedef interval<T, Policies> I;
  252. if (interval_lib::detail::test_input(x, y))
  253. return I::empty();
  254. BOOST_USING_STD_MAX();
  255. return I(max BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y), max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y), true);
  256. }
  257. template<class T, class Policies> inline
  258. interval<T, Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION (const T& x, const interval<T, Policies>& y)
  259. {
  260. typedef interval<T, Policies> I;
  261. if (interval_lib::detail::test_input(x, y))
  262. return I::empty();
  263. BOOST_USING_STD_MAX();
  264. return I(max BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.lower()), max BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.upper()), true);
  265. }
  266. template<class T, class Policies> inline
  267. interval<T, Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x,
  268. const interval<T, Policies>& y)
  269. {
  270. typedef interval<T, Policies> I;
  271. if (interval_lib::detail::test_input(x, y))
  272. return I::empty();
  273. BOOST_USING_STD_MIN();
  274. return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower()), min BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper()), true);
  275. }
  276. template<class T, class Policies> inline
  277. interval<T, Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x, const T& y)
  278. {
  279. typedef interval<T, Policies> I;
  280. if (interval_lib::detail::test_input(x, y))
  281. return I::empty();
  282. BOOST_USING_STD_MIN();
  283. return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y), min BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y), true);
  284. }
  285. template<class T, class Policies> inline
  286. interval<T, Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION (const T& x, const interval<T, Policies>& y)
  287. {
  288. typedef interval<T, Policies> I;
  289. if (interval_lib::detail::test_input(x, y))
  290. return I::empty();
  291. BOOST_USING_STD_MIN();
  292. return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.lower()), min BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.upper()), true);
  293. }
  294. } // namespace numeric
  295. } // namespace boost
  296. #endif // BOOST_NUMERIC_INTERVAL_UTILITY_HPP