1#ifndef BOOST_SAFE_NUMERICS_INTERVAL_HPP
2#define BOOST_SAFE_NUMERICS_INTERVAL_HPP
3
4// Copyright (c) 2012 Robert Ramey
5//
6// Distributed under the Boost Software License, Version 1.0. (See
7// accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9
10#include <limits>
11#include <cassert>
12#include <type_traits>
13#include <initializer_list>
14#include <algorithm> // minmax, min, max
15
16#include <boost/logic/tribool.hpp>
17
18#include "utility.hpp" // log
19
20// from stack overflow
21// http://stackoverflow.com/questions/23815138/implementing-variadic-min-max-functions
22
23namespace boost {
24namespace safe_numerics {
25
26template<typename R>
27struct interval {
28 const R l;
29 const R u;
30
31 template<typename T>
32 constexpr interval(const T & lower, const T & upper) :
33 l(lower),
34 u(upper)
35 {
36 // assert(static_cast<bool>(l <= u));
37 }
38 template<typename T>
39 constexpr interval(const std::pair<T, T> & p) :
40 l(p.first),
41 u(p.second)
42 {}
43 template<class T>
44 constexpr interval(const interval<T> & rhs) :
45 l(rhs.l),
46 u(rhs.u)
47 {}
48 constexpr interval() :
49 l(std::numeric_limits<R>::min()),
50 u(std::numeric_limits<R>::max())
51 {}
52 // return true if this interval contains the given point
53 constexpr tribool includes(const R & t) const {
54 return l <= t && t <= u;
55 }
56 // if this interval contains every point found in some other inteval t
57 // return true
58 // otherwise
59 // return false or indeterminate
60 constexpr tribool includes(const interval<R> & t) const {
61 return u >= t.u && l <= t.l;
62 }
63
64 // return true if this interval contains the given point
65 constexpr tribool excludes(const R & t) const {
66 return t < l || t > u;
67 }
68 // if this interval excludes every point found in some other inteval t
69 // return true
70 // otherwise
71 // return false or indeterminate
72 constexpr tribool excludes(const interval<R> & t) const {
73 return t.u < l || u < t.l;
74 }
75
76};
77
78template<class R>
79constexpr inline interval<R> make_interval(){
80 return interval<R>();
81}
82template<class R>
83constexpr inline interval<R> make_interval(const R &){
84 return interval<R>();
85}
86
87// account for the fact that for floats and doubles
88// the most negative value is called "lowest" rather
89// than min
90template<>
91constexpr inline interval<float>::interval() :
92 l(std::numeric_limits<float>::lowest()),
93 u(std::numeric_limits<float>::max())
94{}
95template<>
96constexpr inline interval<double>::interval() :
97 l(std::numeric_limits<double>::lowest()),
98 u(std::numeric_limits<double>::max())
99{}
100
101template<typename T>
102constexpr inline interval<T> operator+(const interval<T> & t, const interval<T> & u){
103 // adapted from https://en.wikipedia.org/wiki/Interval_arithmetic
104 return {t.l + u.l, t.u + u.u};
105}
106
107template<typename T>
108constexpr inline interval<T> operator-(const interval<T> & t, const interval<T> & u){
109 // adapted from https://en.wikipedia.org/wiki/Interval_arithmetic
110 return {t.l - u.u, t.u - u.l};
111}
112
113template<typename T>
114constexpr inline interval<T> operator*(const interval<T> & t, const interval<T> & u){
115 // adapted from https://en.wikipedia.org/wiki/Interval_arithmetic
116 return utility::minmax<T>(
117 std::initializer_list<T> {
118 t.l * u.l,
119 t.l * u.u,
120 t.u * u.l,
121 t.u * u.u
122 }
123 );
124}
125
126// interval division
127// note: presumes 0 is not included in the range of the denominator
128template<typename T>
129constexpr inline interval<T> operator/(const interval<T> & t, const interval<T> & u){
130 assert(static_cast<bool>(u.excludes(T(0))));
131 return utility::minmax<T>(
132 std::initializer_list<T> {
133 t.l / u.l,
134 t.l / u.u,
135 t.u / u.l,
136 t.u / u.u
137 }
138 );
139}
140
141// modulus of two intervals. This will give a new range of for the modulus.
142// note: presumes 0 is not included in the range of the denominator
143template<typename T>
144constexpr inline interval<T> operator%(const interval<T> & t, const interval<T> & u){
145 assert(static_cast<bool>(u.excludes(T(0))));
146 return utility::minmax<T>(
147 std::initializer_list<T> {
148 t.l % u.l,
149 t.l % u.u,
150 t.u % u.l,
151 t.u % u.u
152 }
153 );
154}
155
156template<typename T>
157constexpr inline interval<T> operator<<(const interval<T> & t, const interval<T> & u){
158 //return interval<T>{t.l << u.l, t.u << u.u};
159 return utility::minmax<T>(
160 std::initializer_list<T> {
161 t.l << u.l,
162 t.l << u.u,
163 t.u << u.l,
164 t.u << u.u
165 }
166 );
167}
168
169template<typename T>
170constexpr inline interval<T> operator>>(const interval<T> & t, const interval<T> & u){
171 //return interval<T>{t.l >> u.u, t.u >> u.l};
172 return utility::minmax<T>(
173 std::initializer_list<T> {
174 t.l >> u.l,
175 t.l >> u.u,
176 t.u >> u.l,
177 t.u >> u.u
178 }
179 );
180}
181
182// union of two intervals
183template<typename T>
184constexpr interval<T> operator|(const interval<T> & t, const interval<T> & u){
185 const T & rl = std::min(t.l, u.l);
186 const T & ru = std::max(t.u, u.u);
187 return interval<T>(rl, ru);
188}
189
190// intersection of two intervals
191template<typename T>
192constexpr inline interval<T> operator&(const interval<T> & t, const interval<T> & u){
193 const T & rl = std::max(t.l, u.l);
194 const T & ru = std::min(t.u, u.u);
195 return interval<T>(rl, ru);
196}
197
198// determine whether two intervals intersect
199template<typename T>
200constexpr inline boost::logic::tribool intersect(const interval<T> & t, const interval<T> & u){
201 return t.u >= u.l || t.l <= u.u;
202}
203
204template<typename T>
205constexpr inline boost::logic::tribool operator<(
206 const interval<T> & t,
207 const interval<T> & u
208){
209 return
210 // if every element in t is less than every element in u
211 t.u < u.l ? boost::logic::tribool(true):
212 // if every element in t is greater than every element in u
213 t.l > u.u ? boost::logic::tribool(false):
214 // otherwise some element(s) in t are greater than some element in u
215 boost::logic::indeterminate
216 ;
217}
218
219template<typename T>
220constexpr inline boost::logic::tribool operator>(
221 const interval<T> & t,
222 const interval<T> & u
223){
224 return
225 // if every element in t is greater than every element in u
226 t.l > u.u ? boost::logic::tribool(true) :
227 // if every element in t is less than every element in u
228 t.u < u.l ? boost::logic::tribool(false) :
229 // otherwise some element(s) in t are greater than some element in u
230 boost::logic::indeterminate
231 ;
232}
233
234template<typename T>
235constexpr inline bool operator==(
236 const interval<T> & t,
237 const interval<T> & u
238){
239 // intervals have the same limits
240 return t.l == u.l && t.u == u.u;
241}
242
243template<typename T>
244constexpr inline bool operator!=(
245 const interval<T> & t,
246 const interval<T> & u
247){
248 return ! (t == u);
249}
250
251template<typename T>
252constexpr inline boost::logic::tribool operator<=(
253 const interval<T> & t,
254 const interval<T> & u
255){
256 return ! (t > u);
257}
258
259template<typename T>
260constexpr inline boost::logic::tribool operator>=(
261 const interval<T> & t,
262 const interval<T> & u
263){
264 return ! (t < u);
265}
266
267} // safe_numerics
268} // boost
269
270#include <iosfwd>
271
272namespace std {
273
274template<typename CharT, typename Traits, typename T>
275inline std::basic_ostream<CharT, Traits> &
276operator<<(
277 std::basic_ostream<CharT, Traits> & os,
278 const boost::safe_numerics::interval<T> & i
279){
280 return os << '[' << i.l << ',' << i.u << ']';
281}
282template<typename CharT, typename Traits>
283inline std::basic_ostream<CharT, Traits> &
284operator<<(
285 std::basic_ostream<CharT, Traits> & os,
286 const boost::safe_numerics::interval<unsigned char> & i
287){
288 os << "[" << (unsigned)i.l << "," << (unsigned)i.u << "]";
289 return os;
290}
291
292template<typename CharT, typename Traits>
293inline std::basic_ostream<CharT, Traits> &
294operator<<(
295 std::basic_ostream<CharT, Traits> & os,
296 const boost::safe_numerics::interval<signed char> & i
297){
298 os << "[" << (int)i.l << "," << (int)i.u << "]";
299 return os;
300}
301
302} // std
303
304#endif // BOOST_SAFE_NUMERICS_INTERVAL_HPP
305

source code of boost/libs/safe_numerics/include/boost/safe_numerics/interval.hpp