template<class T, class Policies> inline interval<T, Policies> operator*(const interval<T, Policies>& x, const interval<T, Policies>& y) { BOOST_NUMERIC_INTERVAL_using_max(min); BOOST_NUMERIC_INTERVAL_using_max(max); typedef interval<T, Policies> I; if (interval_lib::detail::test_input(x, y)) return I::empty(); typename Policies::rounding rnd; const T& xl = x.lower(); const T& xu = x.upper(); const T& yl = y.lower(); const T& yu = y.upper(); if (interval_lib::detail::is_neg(xl)) if (interval_lib::detail::is_pos(xu)) if (interval_lib::detail::is_neg(yl)) if (interval_lib::detail::is_pos(yu)) // M * M return I(min(rnd.mul_down(xl, yu), rnd.mul_down(xu, yl)), max(rnd.mul_up (xl, yl), rnd.mul_up (xu, yu)), true); else // M * N return I(rnd.mul_down(xu, yl), rnd.mul_up(xl, yl), true); else if (interval_lib::detail::is_pos(yu)) // M * P return I(rnd.mul_down(xl, yu), rnd.mul_up(xu, yu), true); else // M * Z return I(0, 0, true); else if (interval_lib::detail::is_neg(yl)) if (interval_lib::detail::is_pos(yu)) // N * M return I(rnd.mul_down(xl, yu), rnd.mul_up(xl, yl), true); else // N * N return I(rnd.mul_down(xu, yu), rnd.mul_up(xl, yl), true); else if (interval_lib::detail::is_pos(yu)) // N * P return I(rnd.mul_down(xl, yu), rnd.mul_up(xu, yl), true); else // N * Z return I(0, 0, true); else if (interval_lib::detail::is_pos(xu)) if (interval_lib::detail::is_neg(yl)) if (interval_lib::detail::is_pos(yu)) // P * M return I(rnd.mul_down(xu, yl), rnd.mul_up(xu, yu), true); else // P * N return I(rnd.mul_down(xu, yl), rnd.mul_up(xl, yu), true); else if (interval_lib::detail::is_pos(yu)) // P * P return I(rnd.mul_down(xl, yl), rnd.mul_up(xu, yu), true); else // P * Z return I(0, 0, true); else // Z * ? return I(0, 0, true); }
template<class T, class Policies> inline interval<T, Policies> intersect(const interval<T, Policies>& x, const interval<T, Policies>& y) { BOOST_NUMERIC_INTERVAL_using_max(min); BOOST_NUMERIC_INTERVAL_using_max(max); if (interval_lib::detail::test_input(x, y)) return interval<T, Policies>::empty(); const T& l = max(x.lower(), y.lower()); const T& u = min(x.upper(), y.upper()); if (l <= u) return interval<T, Policies>(l, u, true); else return interval<T, Policies>::empty(); }
template<class T, class Policies> inline interval<T, Policies> hull(const T& x, const interval<T, Policies>& y) { BOOST_NUMERIC_INTERVAL_using_max(min); BOOST_NUMERIC_INTERVAL_using_max(max); bool bad_x = interval_lib::detail::test_input<T, Policies>(x); bool bad_y = interval_lib::detail::test_input(y); if (bad_x) if (bad_y) return interval<T, Policies>::empty(); else return y; else if (bad_y) return interval<T, Policies>(x, x, true); return interval<T, Policies>(min(x, y.lower()), max(x, y.upper()), true); }
template<class T, class Policies> inline interval<T, Policies> min(const T& x, const interval<T, Policies>& y) { BOOST_NUMERIC_INTERVAL_using_max(min); typedef interval<T, Policies> I; if (interval_lib::detail::test_input(x, y)) return I::empty(); return I(min(x, y.lower()), min(x, y.upper()), true); }
template<class T, class Policies> inline interval<T, Policies> abs(const interval<T, Policies>& x) { BOOST_NUMERIC_INTERVAL_using_max(max); typedef interval<T, Policies> I; if (interval_lib::detail::test_input(x)) return I::empty(); if (!interval_lib::detail::is_neg(x.lower())) return x; if (interval_lib::detail::is_neg(x.upper())) return -x; return I(0, max(-x.lower(), x.upper()), true); }