123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- /* Boost interval/arith.hpp template implementation file
- *
- * Copyright 2000 Jens Maurer
- * Copyright 2002-2003 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
- *
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE_1_0.txt or
- * copy at http://www.boost.org/LICENSE_1_0.txt)
- */
- #ifndef BOOST_NUMERIC_INTERVAL_ARITH_HPP
- #define BOOST_NUMERIC_INTERVAL_ARITH_HPP
- #include <boost/config.hpp>
- #include <boost/numeric/interval/interval.hpp>
- #include <boost/numeric/interval/detail/bugs.hpp>
- #include <boost/numeric/interval/detail/test_input.hpp>
- #include <boost/numeric/interval/detail/division.hpp>
- #include <algorithm>
- namespace boost {
- namespace numeric {
- /*
- * Basic arithmetic operators
- */
- template<class T, class Policies> inline
- const interval<T, Policies>& operator+(const interval<T, Policies>& x)
- {
- return x;
- }
- template<class T, class Policies> inline
- interval<T, Policies> operator-(const interval<T, Policies>& x)
- {
- if (interval_lib::detail::test_input(x))
- return interval<T, Policies>::empty();
- return interval<T, Policies>(-x.upper(), -x.lower(), true);
- }
- template<class T, class Policies> inline
- interval<T, Policies>& interval<T, Policies>::operator+=(const interval<T, Policies>& r)
- {
- if (interval_lib::detail::test_input(*this, r))
- set_empty();
- else {
- typename Policies::rounding rnd;
- set(rnd.add_down(low, r.low), rnd.add_up(up, r.up));
- }
- return *this;
- }
- template<class T, class Policies> inline
- interval<T, Policies>& interval<T, Policies>::operator+=(const T& r)
- {
- if (interval_lib::detail::test_input(*this, r))
- set_empty();
- else {
- typename Policies::rounding rnd;
- set(rnd.add_down(low, r), rnd.add_up(up, r));
- }
- return *this;
- }
- template<class T, class Policies> inline
- interval<T, Policies>& interval<T, Policies>::operator-=(const interval<T, Policies>& r)
- {
- if (interval_lib::detail::test_input(*this, r))
- set_empty();
- else {
- typename Policies::rounding rnd;
- set(rnd.sub_down(low, r.up), rnd.sub_up(up, r.low));
- }
- return *this;
- }
- template<class T, class Policies> inline
- interval<T, Policies>& interval<T, Policies>::operator-=(const T& r)
- {
- if (interval_lib::detail::test_input(*this, r))
- set_empty();
- else {
- typename Policies::rounding rnd;
- set(rnd.sub_down(low, r), rnd.sub_up(up, r));
- }
- return *this;
- }
- template<class T, class Policies> inline
- interval<T, Policies>& interval<T, Policies>::operator*=(const interval<T, Policies>& r)
- {
- return *this = *this * r;
- }
- template<class T, class Policies> inline
- interval<T, Policies>& interval<T, Policies>::operator*=(const T& r)
- {
- return *this = r * *this;
- }
- template<class T, class Policies> inline
- interval<T, Policies>& interval<T, Policies>::operator/=(const interval<T, Policies>& r)
- {
- return *this = *this / r;
- }
- template<class T, class Policies> inline
- interval<T, Policies>& interval<T, Policies>::operator/=(const T& r)
- {
- return *this = *this / r;
- }
- template<class T, class Policies> inline
- interval<T, Policies> operator+(const interval<T, Policies>& x,
- const interval<T, Policies>& y)
- {
- if (interval_lib::detail::test_input(x, y))
- return interval<T, Policies>::empty();
- typename Policies::rounding rnd;
- return interval<T,Policies>(rnd.add_down(x.lower(), y.lower()),
- rnd.add_up (x.upper(), y.upper()), true);
- }
- template<class T, class Policies> inline
- interval<T, Policies> operator+(const T& x, const interval<T, Policies>& y)
- {
- if (interval_lib::detail::test_input(x, y))
- return interval<T, Policies>::empty();
- typename Policies::rounding rnd;
- return interval<T,Policies>(rnd.add_down(x, y.lower()),
- rnd.add_up (x, y.upper()), true);
- }
- template<class T, class Policies> inline
- interval<T, Policies> operator+(const interval<T, Policies>& x, const T& y)
- { return y + x; }
- template<class T, class Policies> inline
- interval<T, Policies> operator-(const interval<T, Policies>& x,
- const interval<T, Policies>& y)
- {
- if (interval_lib::detail::test_input(x, y))
- return interval<T, Policies>::empty();
- typename Policies::rounding rnd;
- return interval<T,Policies>(rnd.sub_down(x.lower(), y.upper()),
- rnd.sub_up (x.upper(), y.lower()), true);
- }
- template<class T, class Policies> inline
- interval<T, Policies> operator-(const T& x, const interval<T, Policies>& y)
- {
- if (interval_lib::detail::test_input(x, y))
- return interval<T, Policies>::empty();
- typename Policies::rounding rnd;
- return interval<T,Policies>(rnd.sub_down(x, y.upper()),
- rnd.sub_up (x, y.lower()), true);
- }
- template<class T, class Policies> inline
- interval<T, Policies> operator-(const interval<T, Policies>& x, const T& y)
- {
- if (interval_lib::detail::test_input(x, y))
- return interval<T, Policies>::empty();
- typename Policies::rounding rnd;
- return interval<T,Policies>(rnd.sub_down(x.lower(), y),
- rnd.sub_up (x.upper(), y), true);
- }
- template<class T, class Policies> inline
- interval<T, Policies> operator*(const interval<T, Policies>& x,
- const interval<T, Policies>& y)
- {
- BOOST_USING_STD_MIN();
- BOOST_USING_STD_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::user::is_neg(xl))
- if (interval_lib::user::is_pos(xu))
- if (interval_lib::user::is_neg(yl))
- if (interval_lib::user::is_pos(yu)) // M * M
- return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(rnd.mul_down(xl, yu), rnd.mul_down(xu, yl)),
- max BOOST_PREVENT_MACRO_SUBSTITUTION(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::user::is_pos(yu)) // M * P
- return I(rnd.mul_down(xl, yu), rnd.mul_up(xu, yu), true);
- else // M * Z
- return I(static_cast<T>(0), static_cast<T>(0), true);
- else
- if (interval_lib::user::is_neg(yl))
- if (interval_lib::user::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::user::is_pos(yu)) // N * P
- return I(rnd.mul_down(xl, yu), rnd.mul_up(xu, yl), true);
- else // N * Z
- return I(static_cast<T>(0), static_cast<T>(0), true);
- else
- if (interval_lib::user::is_pos(xu))
- if (interval_lib::user::is_neg(yl))
- if (interval_lib::user::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::user::is_pos(yu)) // P * P
- return I(rnd.mul_down(xl, yl), rnd.mul_up(xu, yu), true);
- else // P * Z
- return I(static_cast<T>(0), static_cast<T>(0), true);
- else // Z * ?
- return I(static_cast<T>(0), static_cast<T>(0), true);
- }
- template<class T, class Policies> inline
- interval<T, Policies> operator*(const T& x, const interval<T, Policies>& y)
- {
- typedef interval<T, Policies> I;
- if (interval_lib::detail::test_input(x, y))
- return I::empty();
- typename Policies::rounding rnd;
- const T& yl = y.lower();
- const T& yu = y.upper();
- // x is supposed not to be infinite
- if (interval_lib::user::is_neg(x))
- return I(rnd.mul_down(x, yu), rnd.mul_up(x, yl), true);
- else if (interval_lib::user::is_zero(x))
- return I(static_cast<T>(0), static_cast<T>(0), true);
- else
- return I(rnd.mul_down(x, yl), rnd.mul_up(x, yu), true);
- }
- template<class T, class Policies> inline
- interval<T, Policies> operator*(const interval<T, Policies>& x, const T& y)
- { return y * x; }
- template<class T, class Policies> inline
- interval<T, Policies> operator/(const interval<T, Policies>& x,
- const interval<T, Policies>& y)
- {
- if (interval_lib::detail::test_input(x, y))
- return interval<T, Policies>::empty();
- if (zero_in(y))
- if (!interval_lib::user::is_zero(y.lower()))
- if (!interval_lib::user::is_zero(y.upper()))
- return interval_lib::detail::div_zero(x);
- else
- return interval_lib::detail::div_negative(x, y.lower());
- else
- if (!interval_lib::user::is_zero(y.upper()))
- return interval_lib::detail::div_positive(x, y.upper());
- else
- return interval<T, Policies>::empty();
- else
- return interval_lib::detail::div_non_zero(x, y);
- }
- template<class T, class Policies> inline
- interval<T, Policies> operator/(const T& x, const interval<T, Policies>& y)
- {
- if (interval_lib::detail::test_input(x, y))
- return interval<T, Policies>::empty();
- if (zero_in(y))
- if (!interval_lib::user::is_zero(y.lower()))
- if (!interval_lib::user::is_zero(y.upper()))
- return interval_lib::detail::div_zero<T, Policies>(x);
- else
- return interval_lib::detail::div_negative<T, Policies>(x, y.lower());
- else
- if (!interval_lib::user::is_zero(y.upper()))
- return interval_lib::detail::div_positive<T, Policies>(x, y.upper());
- else
- return interval<T, Policies>::empty();
- else
- return interval_lib::detail::div_non_zero(x, y);
- }
- template<class T, class Policies> inline
- interval<T, Policies> operator/(const interval<T, Policies>& x, const T& y)
- {
- if (interval_lib::detail::test_input(x, y) || interval_lib::user::is_zero(y))
- return interval<T, Policies>::empty();
- typename Policies::rounding rnd;
- const T& xl = x.lower();
- const T& xu = x.upper();
- if (interval_lib::user::is_neg(y))
- return interval<T, Policies>(rnd.div_down(xu, y), rnd.div_up(xl, y), true);
- else
- return interval<T, Policies>(rnd.div_down(xl, y), rnd.div_up(xu, y), true);
- }
- } // namespace numeric
- } // namespace boost
- #endif // BOOST_NUMERIC_INTERVAL_ARITH_HPP
|