1 /* Boost interval/utility.hpp template implementation file
2 *
3 * Copyright 2000 Jens Maurer
4 * Copyright 2002-2003 Herv� Br�nnimann, Guillaume Melquiond, Sylvain Pion
5 *
6 * Distributed under the Boost Software License, Version 1.0.
7 * (See accompanying file LICENSE_1_0.txt or
8 * copy at http://www.boost.org/LICENSE_1_0.txt)
9 */
10
11 #ifndef BOOST_NUMERIC_INTERVAL_UTILITY_HPP
12 #define BOOST_NUMERIC_INTERVAL_UTILITY_HPP
13
14 #include <boost/config.hpp>
15 #include <boost/numeric/interval/detail/interval_prototype.hpp>
16 #include <boost/numeric/interval/detail/test_input.hpp>
17 #include <boost/numeric/interval/detail/bugs.hpp>
18 #include <algorithm>
19 #include <utility>
20
21 /*
22 * Implementation of simple functions
23 */
24
25 namespace boost {
26 namespace numeric {
27
28 /*
29 * Utility Functions
30 */
31
32 template<class T, class Policies> inline
lower(const interval<T,Policies> & x)33 const T& lower(const interval<T, Policies>& x)
34 {
35 return x.lower();
36 }
37
38 template<class T, class Policies> inline
upper(const interval<T,Policies> & x)39 const T& upper(const interval<T, Policies>& x)
40 {
41 return x.upper();
42 }
43
44 template<class T, class Policies> inline
checked_lower(const interval<T,Policies> & x)45 T checked_lower(const interval<T, Policies>& x)
46 {
47 if (empty(x)) {
48 typedef typename Policies::checking checking;
49 return checking::nan();
50 }
51 return x.lower();
52 }
53
54 template<class T, class Policies> inline
checked_upper(const interval<T,Policies> & x)55 T checked_upper(const interval<T, Policies>& x)
56 {
57 if (empty(x)) {
58 typedef typename Policies::checking checking;
59 return checking::nan();
60 }
61 return x.upper();
62 }
63
64 template<class T, class Policies> inline
width(const interval<T,Policies> & x)65 T width(const interval<T, Policies>& x)
66 {
67 if (interval_lib::detail::test_input(x)) return static_cast<T>(0);
68 typename Policies::rounding rnd;
69 return rnd.sub_up(x.upper(), x.lower());
70 }
71
72 template<class T, class Policies> inline
median(const interval<T,Policies> & x)73 T median(const interval<T, Policies>& x)
74 {
75 if (interval_lib::detail::test_input(x)) {
76 typedef typename Policies::checking checking;
77 return checking::nan();
78 }
79 typename Policies::rounding rnd;
80 return rnd.median(x.lower(), x.upper());
81 }
82
83 template<class T, class Policies> inline
widen(const interval<T,Policies> & x,const T & v)84 interval<T, Policies> widen(const interval<T, Policies>& x, const T& v)
85 {
86 if (interval_lib::detail::test_input(x))
87 return interval<T, Policies>::empty();
88 typename Policies::rounding rnd;
89 return interval<T, Policies>(rnd.sub_down(x.lower(), v),
90 rnd.add_up (x.upper(), v), true);
91 }
92
93 /*
94 * Set-like operations
95 */
96
97 template<class T, class Policies> inline
empty(const interval<T,Policies> & x)98 bool empty(const interval<T, Policies>& x)
99 {
100 return interval_lib::detail::test_input(x);
101 }
102
103 template<class T, class Policies> inline
in_zero(const interval<T,Policies> & x)104 bool in_zero(const interval<T, Policies>& x)
105 {
106 if (interval_lib::detail::test_input(x)) return false;
107 return (!interval_lib::user::is_pos(x.lower())) &&
108 (!interval_lib::user::is_neg(x.upper()));
109 }
110
111 template<class T, class Policies> inline
in(const T & x,const interval<T,Policies> & y)112 bool in(const T& x, const interval<T, Policies>& y)
113 {
114 if (interval_lib::detail::test_input(x, y)) return false;
115 return y.lower() <= x && x <= y.upper();
116 }
117
118 template<class T, class Policies> inline
subset(const interval<T,Policies> & x,const interval<T,Policies> & y)119 bool subset(const interval<T, Policies>& x,
120 const interval<T, Policies>& y)
121 {
122 if (empty(x)) return true;
123 return !empty(y) && y.lower() <= x.lower() && x.upper() <= y.upper();
124 }
125
126 template<class T, class Policies1, class Policies2> inline
proper_subset(const interval<T,Policies1> & x,const interval<T,Policies2> & y)127 bool proper_subset(const interval<T, Policies1>& x,
128 const interval<T, Policies2>& y)
129 {
130 if (empty(y)) return false;
131 if (empty(x)) return true;
132 return y.lower() <= x.lower() && x.upper() <= y.upper() &&
133 (y.lower() != x.lower() || x.upper() != y.upper());
134 }
135
136 template<class T, class Policies1, class Policies2> inline
overlap(const interval<T,Policies1> & x,const interval<T,Policies2> & y)137 bool overlap(const interval<T, Policies1>& x,
138 const interval<T, Policies2>& y)
139 {
140 if (interval_lib::detail::test_input(x, y)) return false;
141 return x.lower() <= y.lower() && y.lower() <= x.upper() ||
142 y.lower() <= x.lower() && x.lower() <= y.upper();
143 }
144
145 template<class T, class Policies> inline
singleton(const interval<T,Policies> & x)146 bool singleton(const interval<T, Policies>& x)
147 {
148 return !empty(x) && x.lower() == x.upper();
149 }
150
151 template<class T, class Policies1, class Policies2> inline
equal(const interval<T,Policies1> & x,const interval<T,Policies2> & y)152 bool equal(const interval<T, Policies1>& x, const interval<T, Policies2>& y)
153 {
154 if (empty(x)) return empty(y);
155 return !empty(y) && x.lower() == y.lower() && x.upper() == y.upper();
156 }
157
158 template<class T, class Policies> inline
intersect(const interval<T,Policies> & x,const interval<T,Policies> & y)159 interval<T, Policies> intersect(const interval<T, Policies>& x,
160 const interval<T, Policies>& y)
161 {
162 BOOST_USING_STD_MIN();
163 BOOST_USING_STD_MAX();
164 if (interval_lib::detail::test_input(x, y))
165 return interval<T, Policies>::empty();
166 const T& l = max BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower());
167 const T& u = min BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper());
168 if (l <= u) return interval<T, Policies>(l, u, true);
169 else return interval<T, Policies>::empty();
170 }
171
172 template<class T, class Policies> inline
hull(const interval<T,Policies> & x,const interval<T,Policies> & y)173 interval<T, Policies> hull(const interval<T, Policies>& x,
174 const interval<T, Policies>& y)
175 {
176 BOOST_USING_STD_MIN();
177 BOOST_USING_STD_MAX();
178 bool bad_x = interval_lib::detail::test_input(x);
179 bool bad_y = interval_lib::detail::test_input(y);
180 if (bad_x)
181 if (bad_y) return interval<T, Policies>::empty();
182 else return y;
183 else
184 if (bad_y) return x;
185 return interval<T, Policies>(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower()),
186 max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper()), true);
187 }
188
189 template<class T, class Policies> inline
hull(const interval<T,Policies> & x,const T & y)190 interval<T, Policies> hull(const interval<T, Policies>& x, const T& y)
191 {
192 BOOST_USING_STD_MIN();
193 BOOST_USING_STD_MAX();
194 bool bad_x = interval_lib::detail::test_input(x);
195 bool bad_y = interval_lib::detail::test_input<T, Policies>(y);
196 if (bad_y)
197 if (bad_x) return interval<T, Policies>::empty();
198 else return x;
199 else
200 if (bad_x) return interval<T, Policies>(y, y, true);
201 return interval<T, Policies>(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y),
202 max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y), true);
203 }
204
205 template<class T, class Policies> inline
hull(const T & x,const interval<T,Policies> & y)206 interval<T, Policies> hull(const T& x, const interval<T, Policies>& y)
207 {
208 BOOST_USING_STD_MIN();
209 BOOST_USING_STD_MAX();
210 bool bad_x = interval_lib::detail::test_input<T, Policies>(x);
211 bool bad_y = interval_lib::detail::test_input(y);
212 if (bad_x)
213 if (bad_y) return interval<T, Policies>::empty();
214 else return y;
215 else
216 if (bad_y) return interval<T, Policies>(x, x, true);
217 return interval<T, Policies>(min BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.lower()),
218 max BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.upper()), true);
219 }
220
221 template<class T> inline
hull(const T & x,const T & y)222 interval<T> hull(const T& x, const T& y)
223 {
224 return interval<T>::hull(x, y);
225 }
226
227 template<class T, class Policies> inline
228 std::pair<interval<T, Policies>, interval<T, Policies> >
bisect(const interval<T,Policies> & x)229 bisect(const interval<T, Policies>& x)
230 {
231 typedef interval<T, Policies> I;
232 if (interval_lib::detail::test_input(x))
233 return std::pair<I,I>(I::empty(), I::empty());
234 const T m = median(x);
235 return std::pair<I,I>(I(x.lower(), m, true), I(m, x.upper(), true));
236 }
237
238 /*
239 * Elementary functions
240 */
241
242 template<class T, class Policies> inline
norm(const interval<T,Policies> & x)243 T norm(const interval<T, Policies>& x)
244 {
245 typedef interval<T, Policies> I;
246 if (interval_lib::detail::test_input(x)) {
247 typedef typename Policies::checking checking;
248 return checking::nan();
249 }
250 BOOST_USING_STD_MAX();
251 return max BOOST_PREVENT_MACRO_SUBSTITUTION(-x.lower(), x.upper());
252 }
253
254 template<class T, class Policies> inline
abs(const interval<T,Policies> & x)255 interval<T, Policies> abs(const interval<T, Policies>& x)
256 {
257 typedef interval<T, Policies> I;
258 if (interval_lib::detail::test_input(x))
259 return I::empty();
260 if (!interval_lib::user::is_neg(x.lower())) return x;
261 if (!interval_lib::user::is_pos(x.upper())) return -x;
262 BOOST_USING_STD_MAX();
263 return I(static_cast<T>(0), max BOOST_PREVENT_MACRO_SUBSTITUTION(-x.lower(), x.upper()), true);
264 }
265
266 template<class T, class Policies> inline
BOOST_PREVENT_MACRO_SUBSTITUTION(const interval<T,Policies> & x,const interval<T,Policies> & y)267 interval<T, Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x,
268 const interval<T, Policies>& y)
269 {
270 typedef interval<T, Policies> I;
271 if (interval_lib::detail::test_input(x, y))
272 return I::empty();
273 BOOST_USING_STD_MAX();
274 return I(max BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower()), max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper()), true);
275 }
276
277 template<class T, class Policies> inline
BOOST_PREVENT_MACRO_SUBSTITUTION(const interval<T,Policies> & x,const T & y)278 interval<T, Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x, const T& y)
279 {
280 typedef interval<T, Policies> I;
281 if (interval_lib::detail::test_input(x, y))
282 return I::empty();
283 BOOST_USING_STD_MAX();
284 return I(max BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y), max BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y), true);
285 }
286
287 template<class T, class Policies> inline
BOOST_PREVENT_MACRO_SUBSTITUTION(const T & x,const interval<T,Policies> & y)288 interval<T, Policies> max BOOST_PREVENT_MACRO_SUBSTITUTION (const T& x, const interval<T, Policies>& y)
289 {
290 typedef interval<T, Policies> I;
291 if (interval_lib::detail::test_input(x, y))
292 return I::empty();
293 BOOST_USING_STD_MAX();
294 return I(max BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.lower()), max BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.upper()), true);
295 }
296
297 template<class T, class Policies> inline
BOOST_PREVENT_MACRO_SUBSTITUTION(const interval<T,Policies> & x,const interval<T,Policies> & y)298 interval<T, Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x,
299 const interval<T, Policies>& y)
300 {
301 typedef interval<T, Policies> I;
302 if (interval_lib::detail::test_input(x, y))
303 return I::empty();
304 BOOST_USING_STD_MIN();
305 return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y.lower()), min BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y.upper()), true);
306 }
307
308 template<class T, class Policies> inline
BOOST_PREVENT_MACRO_SUBSTITUTION(const interval<T,Policies> & x,const T & y)309 interval<T, Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION (const interval<T, Policies>& x, const T& y)
310 {
311 typedef interval<T, Policies> I;
312 if (interval_lib::detail::test_input(x, y))
313 return I::empty();
314 BOOST_USING_STD_MIN();
315 return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(x.lower(), y), min BOOST_PREVENT_MACRO_SUBSTITUTION(x.upper(), y), true);
316 }
317
318 template<class T, class Policies> inline
BOOST_PREVENT_MACRO_SUBSTITUTION(const T & x,const interval<T,Policies> & y)319 interval<T, Policies> min BOOST_PREVENT_MACRO_SUBSTITUTION (const T& x, const interval<T, Policies>& y)
320 {
321 typedef interval<T, Policies> I;
322 if (interval_lib::detail::test_input(x, y))
323 return I::empty();
324 BOOST_USING_STD_MIN();
325 return I(min BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.lower()), min BOOST_PREVENT_MACRO_SUBSTITUTION(x, y.upper()), true);
326 }
327
328 } // namespace numeric
329 } // namespace boost
330
331 #endif // BOOST_NUMERIC_INTERVAL_UTILITY_HPP
332