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