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