division.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /* Boost interval/detail/division.hpp file
  2. *
  3. * Copyright 2003 Guillaume Melquiond, Sylvain Pion
  4. *
  5. * Distributed under the Boost Software License, Version 1.0.
  6. * (See accompanying file LICENSE_1_0.txt or
  7. * copy at http://www.boost.org/LICENSE_1_0.txt)
  8. */
  9. #ifndef BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP
  10. #define BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP
  11. #include <boost/numeric/interval/detail/interval_prototype.hpp>
  12. #include <boost/numeric/interval/detail/bugs.hpp>
  13. #include <boost/numeric/interval/detail/test_input.hpp>
  14. #include <boost/numeric/interval/rounded_arith.hpp>
  15. #include <algorithm>
  16. namespace boost {
  17. namespace numeric {
  18. namespace interval_lib {
  19. namespace detail {
  20. template<class T, class Policies> inline
  21. interval<T, Policies> div_non_zero(const interval<T, Policies>& x,
  22. const interval<T, Policies>& y)
  23. {
  24. // assert(!in_zero(y));
  25. typename Policies::rounding rnd;
  26. typedef interval<T, Policies> I;
  27. const T& xl = x.lower();
  28. const T& xu = x.upper();
  29. const T& yl = y.lower();
  30. const T& yu = y.upper();
  31. if (::boost::numeric::interval_lib::user::is_neg(xu))
  32. if (::boost::numeric::interval_lib::user::is_neg(yu))
  33. return I(rnd.div_down(xu, yl), rnd.div_up(xl, yu), true);
  34. else
  35. return I(rnd.div_down(xl, yl), rnd.div_up(xu, yu), true);
  36. else if (::boost::numeric::interval_lib::user::is_neg(xl))
  37. if (::boost::numeric::interval_lib::user::is_neg(yu))
  38. return I(rnd.div_down(xu, yu), rnd.div_up(xl, yu), true);
  39. else
  40. return I(rnd.div_down(xl, yl), rnd.div_up(xu, yl), true);
  41. else
  42. if (::boost::numeric::interval_lib::user::is_neg(yu))
  43. return I(rnd.div_down(xu, yu), rnd.div_up(xl, yl), true);
  44. else
  45. return I(rnd.div_down(xl, yu), rnd.div_up(xu, yl), true);
  46. }
  47. template<class T, class Policies> inline
  48. interval<T, Policies> div_non_zero(const T& x, const interval<T, Policies>& y)
  49. {
  50. // assert(!in_zero(y));
  51. typename Policies::rounding rnd;
  52. typedef interval<T, Policies> I;
  53. const T& yl = y.lower();
  54. const T& yu = y.upper();
  55. if (::boost::numeric::interval_lib::user::is_neg(x))
  56. return I(rnd.div_down(x, yl), rnd.div_up(x, yu), true);
  57. else
  58. return I(rnd.div_down(x, yu), rnd.div_up(x, yl), true);
  59. }
  60. template<class T, class Policies> inline
  61. interval<T, Policies> div_positive(const interval<T, Policies>& x, const T& yu)
  62. {
  63. // assert(::boost::numeric::interval_lib::user::is_pos(yu));
  64. if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
  65. ::boost::numeric::interval_lib::user::is_zero(x.upper()))
  66. return x;
  67. typename Policies::rounding rnd;
  68. typedef interval<T, Policies> I;
  69. const T& xl = x.lower();
  70. const T& xu = x.upper();
  71. typedef typename Policies::checking checking;
  72. if (::boost::numeric::interval_lib::user::is_neg(xu))
  73. return I(checking::neg_inf(), rnd.div_up(xu, yu), true);
  74. else if (::boost::numeric::interval_lib::user::is_neg(xl))
  75. return I(checking::neg_inf(), checking::pos_inf(), true);
  76. else
  77. return I(rnd.div_down(xl, yu), checking::pos_inf(), true);
  78. }
  79. template<class T, class Policies> inline
  80. interval<T, Policies> div_positive(const T& x, const T& yu)
  81. {
  82. // assert(::boost::numeric::interval_lib::user::is_pos(yu));
  83. typedef interval<T, Policies> I;
  84. if (::boost::numeric::interval_lib::user::is_zero(x))
  85. return I(static_cast<T>(0), static_cast<T>(0), true);
  86. typename Policies::rounding rnd;
  87. typedef typename Policies::checking checking;
  88. if (::boost::numeric::interval_lib::user::is_neg(x))
  89. return I(checking::neg_inf(), rnd.div_up(x, yu), true);
  90. else
  91. return I(rnd.div_down(x, yu), checking::pos_inf(), true);
  92. }
  93. template<class T, class Policies> inline
  94. interval<T, Policies> div_negative(const interval<T, Policies>& x, const T& yl)
  95. {
  96. // assert(::boost::numeric::interval_lib::user::is_neg(yl));
  97. if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
  98. ::boost::numeric::interval_lib::user::is_zero(x.upper()))
  99. return x;
  100. typename Policies::rounding rnd;
  101. typedef interval<T, Policies> I;
  102. const T& xl = x.lower();
  103. const T& xu = x.upper();
  104. typedef typename Policies::checking checking;
  105. if (::boost::numeric::interval_lib::user::is_neg(xu))
  106. return I(rnd.div_down(xu, yl), checking::pos_inf(), true);
  107. else if (::boost::numeric::interval_lib::user::is_neg(xl))
  108. return I(checking::neg_inf(), checking::pos_inf(), true);
  109. else
  110. return I(checking::neg_inf(), rnd.div_up(xl, yl), true);
  111. }
  112. template<class T, class Policies> inline
  113. interval<T, Policies> div_negative(const T& x, const T& yl)
  114. {
  115. // assert(::boost::numeric::interval_lib::user::is_neg(yl));
  116. typedef interval<T, Policies> I;
  117. if (::boost::numeric::interval_lib::user::is_zero(x))
  118. return I(static_cast<T>(0), static_cast<T>(0), true);
  119. typename Policies::rounding rnd;
  120. typedef typename Policies::checking checking;
  121. if (::boost::numeric::interval_lib::user::is_neg(x))
  122. return I(rnd.div_down(x, yl), checking::pos_inf(), true);
  123. else
  124. return I(checking::neg_inf(), rnd.div_up(x, yl), true);
  125. }
  126. template<class T, class Policies> inline
  127. interval<T, Policies> div_zero(const interval<T, Policies>& x)
  128. {
  129. if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
  130. ::boost::numeric::interval_lib::user::is_zero(x.upper()))
  131. return x;
  132. else return interval<T, Policies>::whole();
  133. }
  134. template<class T, class Policies> inline
  135. interval<T, Policies> div_zero(const T& x)
  136. {
  137. if (::boost::numeric::interval_lib::user::is_zero(x))
  138. return interval<T, Policies>(static_cast<T>(0), static_cast<T>(0), true);
  139. else return interval<T, Policies>::whole();
  140. }
  141. template<class T, class Policies> inline
  142. interval<T, Policies> div_zero_part1(const interval<T, Policies>& x,
  143. const interval<T, Policies>& y, bool& b)
  144. {
  145. // assert(::boost::numeric::interval_lib::user::is_neg(y.lower()) && ::boost::numeric::interval_lib::user::is_pos(y.upper()));
  146. if (::boost::numeric::interval_lib::user::is_zero(x.lower()) && ::boost::numeric::interval_lib::user::is_zero(x.upper()))
  147. { b = false; return x; }
  148. typename Policies::rounding rnd;
  149. typedef interval<T, Policies> I;
  150. const T& xl = x.lower();
  151. const T& xu = x.upper();
  152. const T& yl = y.lower();
  153. const T& yu = y.upper();
  154. typedef typename Policies::checking checking;
  155. if (::boost::numeric::interval_lib::user::is_neg(xu))
  156. { b = true; return I(checking::neg_inf(), rnd.div_up(xu, yu), true); }
  157. else if (::boost::numeric::interval_lib::user::is_neg(xl))
  158. { b = false; return I(checking::neg_inf(), checking::pos_inf(), true); }
  159. else
  160. { b = true; return I(checking::neg_inf(), rnd.div_up(xl, yl), true); }
  161. }
  162. template<class T, class Policies> inline
  163. interval<T, Policies> div_zero_part2(const interval<T, Policies>& x,
  164. const interval<T, Policies>& y)
  165. {
  166. // assert(::boost::numeric::interval_lib::user::is_neg(y.lower()) && ::boost::numeric::interval_lib::user::is_pos(y.upper()) && (div_zero_part1(x, y, b), b));
  167. typename Policies::rounding rnd;
  168. typedef interval<T, Policies> I;
  169. typedef typename Policies::checking checking;
  170. if (::boost::numeric::interval_lib::user::is_neg(x.upper()))
  171. return I(rnd.div_down(x.upper(), y.lower()), checking::pos_inf(), true);
  172. else
  173. return I(rnd.div_down(x.lower(), y.upper()), checking::pos_inf(), true);
  174. }
  175. } // namespace detail
  176. } // namespace interval_lib
  177. } // namespace numeric
  178. } // namespace boost
  179. #endif // BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP