1 /* Boost interval/detail/division.hpp file
3 * Copyright 2003 Guillaume Melquiond, Sylvain Pion
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)
10 #ifndef BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP
11 #define BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP
13 #include <boost/numeric/interval/detail/interval_prototype.hpp>
14 #include <boost/numeric/interval/detail/bugs.hpp>
15 #include <boost/numeric/interval/detail/test_input.hpp>
16 #include <boost/numeric/interval/rounded_arith.hpp>
21 namespace interval_lib {
24 template<class T, class Policies> inline
25 interval<T, Policies> div_non_zero(const interval<T, Policies>& x,
26 const interval<T, Policies>& y)
28 // assert(!in_zero(y));
29 typename Policies::rounding rnd;
30 typedef interval<T, Policies> I;
31 const T& xl = x.lower();
32 const T& xu = x.upper();
33 const T& yl = y.lower();
34 const T& yu = y.upper();
35 if (::boost::numeric::interval_lib::user::is_neg(xu))
36 if (::boost::numeric::interval_lib::user::is_neg(yu))
37 return I(rnd.div_down(xu, yl), rnd.div_up(xl, yu), true);
39 return I(rnd.div_down(xl, yl), rnd.div_up(xu, yu), true);
40 else if (::boost::numeric::interval_lib::user::is_neg(xl))
41 if (::boost::numeric::interval_lib::user::is_neg(yu))
42 return I(rnd.div_down(xu, yu), rnd.div_up(xl, yu), true);
44 return I(rnd.div_down(xl, yl), rnd.div_up(xu, yl), true);
46 if (::boost::numeric::interval_lib::user::is_neg(yu))
47 return I(rnd.div_down(xu, yu), rnd.div_up(xl, yl), true);
49 return I(rnd.div_down(xl, yu), rnd.div_up(xu, yl), true);
52 template<class T, class Policies> inline
53 interval<T, Policies> div_non_zero(const T& x, const interval<T, Policies>& y)
55 // assert(!in_zero(y));
56 typename Policies::rounding rnd;
57 typedef interval<T, Policies> I;
58 const T& yl = y.lower();
59 const T& yu = y.upper();
60 if (::boost::numeric::interval_lib::user::is_neg(x))
61 return I(rnd.div_down(x, yl), rnd.div_up(x, yu), true);
63 return I(rnd.div_down(x, yu), rnd.div_up(x, yl), true);
66 template<class T, class Policies> inline
67 interval<T, Policies> div_positive(const interval<T, Policies>& x, const T& yu)
69 // assert(::boost::numeric::interval_lib::user::is_pos(yu));
70 if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
71 ::boost::numeric::interval_lib::user::is_zero(x.upper()))
73 typename Policies::rounding rnd;
74 typedef interval<T, Policies> I;
75 const T& xl = x.lower();
76 const T& xu = x.upper();
77 typedef typename Policies::checking checking;
78 if (::boost::numeric::interval_lib::user::is_neg(xu))
79 return I(checking::neg_inf(), rnd.div_up(xu, yu), true);
80 else if (::boost::numeric::interval_lib::user::is_neg(xl))
81 return I(checking::neg_inf(), checking::pos_inf(), true);
83 return I(rnd.div_down(xl, yu), checking::pos_inf(), true);
86 template<class T, class Policies> inline
87 interval<T, Policies> div_positive(const T& x, const T& yu)
89 // assert(::boost::numeric::interval_lib::user::is_pos(yu));
90 typedef interval<T, Policies> I;
91 if (::boost::numeric::interval_lib::user::is_zero(x))
92 return I(static_cast<T>(0), static_cast<T>(0), true);
93 typename Policies::rounding rnd;
94 typedef typename Policies::checking checking;
95 if (::boost::numeric::interval_lib::user::is_neg(x))
96 return I(checking::neg_inf(), rnd.div_up(x, yu), true);
98 return I(rnd.div_down(x, yu), checking::pos_inf(), true);
101 template<class T, class Policies> inline
102 interval<T, Policies> div_negative(const interval<T, Policies>& x, const T& yl)
104 // assert(::boost::numeric::interval_lib::user::is_neg(yl));
105 if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
106 ::boost::numeric::interval_lib::user::is_zero(x.upper()))
108 typename Policies::rounding rnd;
109 typedef interval<T, Policies> I;
110 const T& xl = x.lower();
111 const T& xu = x.upper();
112 typedef typename Policies::checking checking;
113 if (::boost::numeric::interval_lib::user::is_neg(xu))
114 return I(rnd.div_down(xu, yl), checking::pos_inf(), true);
115 else if (::boost::numeric::interval_lib::user::is_neg(xl))
116 return I(checking::neg_inf(), checking::pos_inf(), true);
118 return I(checking::neg_inf(), rnd.div_up(xl, yl), true);
121 template<class T, class Policies> inline
122 interval<T, Policies> div_negative(const T& x, const T& yl)
124 // assert(::boost::numeric::interval_lib::user::is_neg(yl));
125 typedef interval<T, Policies> I;
126 if (::boost::numeric::interval_lib::user::is_zero(x))
127 return I(static_cast<T>(0), static_cast<T>(0), true);
128 typename Policies::rounding rnd;
129 typedef typename Policies::checking checking;
130 if (::boost::numeric::interval_lib::user::is_neg(x))
131 return I(rnd.div_down(x, yl), checking::pos_inf(), true);
133 return I(checking::neg_inf(), rnd.div_up(x, yl), true);
136 template<class T, class Policies> inline
137 interval<T, Policies> div_zero(const interval<T, Policies>& x)
139 if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
140 ::boost::numeric::interval_lib::user::is_zero(x.upper()))
142 else return interval<T, Policies>::whole();
145 template<class T, class Policies> inline
146 interval<T, Policies> div_zero(const T& x)
148 if (::boost::numeric::interval_lib::user::is_zero(x))
149 return interval<T, Policies>(static_cast<T>(0), static_cast<T>(0), true);
150 else return interval<T, Policies>::whole();
153 template<class T, class Policies> inline
154 interval<T, Policies> div_zero_part1(const interval<T, Policies>& x,
155 const interval<T, Policies>& y, bool& b)
157 // assert(::boost::numeric::interval_lib::user::is_neg(y.lower()) && ::boost::numeric::interval_lib::user::is_pos(y.upper()));
158 if (::boost::numeric::interval_lib::user::is_zero(x.lower()) && ::boost::numeric::interval_lib::user::is_zero(x.upper()))
159 { b = false; return x; }
160 typename Policies::rounding rnd;
161 typedef interval<T, Policies> I;
162 const T& xl = x.lower();
163 const T& xu = x.upper();
164 const T& yl = y.lower();
165 const T& yu = y.upper();
166 typedef typename Policies::checking checking;
167 if (::boost::numeric::interval_lib::user::is_neg(xu))
168 { b = true; return I(checking::neg_inf(), rnd.div_up(xu, yu), true); }
169 else if (::boost::numeric::interval_lib::user::is_neg(xl))
170 { b = false; return I(checking::neg_inf(), checking::pos_inf(), true); }
172 { b = true; return I(checking::neg_inf(), rnd.div_up(xl, yl), true); }
175 template<class T, class Policies> inline
176 interval<T, Policies> div_zero_part2(const interval<T, Policies>& x,
177 const interval<T, Policies>& y)
179 // 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));
180 typename Policies::rounding rnd;
181 typedef interval<T, Policies> I;
182 typedef typename Policies::checking checking;
183 if (::boost::numeric::interval_lib::user::is_neg(x.upper()))
184 return I(rnd.div_down(x.upper(), y.lower()), checking::pos_inf(), true);
186 return I(rnd.div_down(x.lower(), y.upper()), checking::pos_inf(), true);
189 } // namespace detail
190 } // namespace interval_lib
191 } // namespace numeric
194 #endif // BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP