ROSE 0.11.145.147
Interval.h
1// WARNING: Changes to this file must be contributed back to Sawyer or else they will
2// be clobbered by the next update from Sawyer. The Sawyer repository is at
3// https://gitlab.com/charger7534/sawyer.git.
4
5
6
7
8#ifndef Sawyer_Interval_H
9#define Sawyer_Interval_H
10
11#include <Sawyer/Assert.h>
12#include <Sawyer/Sawyer.h>
13#include <boost/integer_traits.hpp>
14#include <boost/iterator/iterator_facade.hpp>
15#include <boost/range/iterator_range.hpp>
16
17namespace Sawyer {
18namespace Container {
19
30template<class T>
31class Interval {
32public:
34 typedef T Value;
35private:
36 T lo_, hi_;
37
38#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
39private:
40 friend class boost::serialization::access;
41
42 template<class S>
43 void serialize(S &s, const unsigned /*version*/) {
44 s & BOOST_SERIALIZATION_NVP(lo_);
45 s & BOOST_SERIALIZATION_NVP(hi_);
46 }
47#endif
48
49#ifdef SAWYER_HAVE_CEREAL
50private:
51 friend class cereal::access;
52
53 template<class Archive>
54 void CEREAL_SERIALIZE_FUNCTION_NAME(Archive &archive) {
55 archive(CEREAL_NVP(lo_));
56 archive(CEREAL_NVP(hi_));
57 }
58#endif
59
60public:
74 class ConstIterator: public boost::iterator_facade<ConstIterator, const Value, boost::bidirectional_traversal_tag,
75 Value> {
76 friend class Interval;
77 friend class boost::iterator_core_access;
78
79 T first_, cur_, last_;
80 bool atEnd_;
81
82 ConstIterator(T first, T last, T cur): first_(first), cur_(cur), last_(last), atEnd_(false) {}
83 public:
89 ConstIterator(): first_(0), cur_(0), last_(0), atEnd_(true) {}
90
96 bool atEnd() const {
97 return atEnd_;
98 }
99
100 private:
101 Value dereference() const {
102 ASSERT_forbid(atEnd());
103 return cur_;
104 }
105
106 bool equal(const ConstIterator &other) const {
107 if (atEnd() || other.atEnd())
108 return atEnd() && other.atEnd();
109 return cur_ == other.cur_;
110 }
111
112 // Incrementing an iterator associated with an empty interval is a no-op, and such an interval's @ref atEnd always
113 // returns true. Otherwise, incrementing an iterator positioned one past the interval's greatest end is a
114 // no-op. Otherwise, incrementing an iterator positioned one prior to the interval's least end returns the iterator to
115 // the interval's least value. Otherwise the iterator derefences to a value one greater than before this call.
116 void increment() {
117 if (cur_ == last_) { // avoid overflow
118 atEnd_ = true;
119 } else if (atEnd_) {
120 ASSERT_require(cur_ == first_);
121 atEnd_ = false;
122 } else {
123 ++cur_;
124 }
125 }
126
127 void decrement() {
128 if (cur_ == first_) { // avoid overflow
129 atEnd_ = true;
130 } else if (atEnd_) {
131 ASSERT_require(cur_ == last_);
132 atEnd_ = false;
133 } else {
134 --cur_;
135 }
136 }
137 };
138
139public:
141 Interval(): lo_(1), hi_(0) {}
142
144 Interval(const Interval &other): lo_(other.lo_), hi_(other.hi_) {}
145
147 Interval(T value): lo_(value), hi_(value) {}
148
149#if 0 // [Robb Matzke 2014-05-14]: too much confusion with "hi" vs. "size". Use either baseSize or hull instead.
154 Interval(T lo, T hi): lo_(lo), hi_(hi) {
155 ASSERT_require(lo <= hi);
156 }
157#endif
158
162 static Interval hull(T v1, T v2) {
163 Interval retval;
164 retval.lo_ = std::min(v1, v2);
165 retval.hi_ = std::max(v1, v2);
166 return retval;
167 }
168
173 static Interval baseSize(T lo, T size) {
174 ASSERT_forbid(baseSizeOverflows(lo, size));
175 return 0==size ? Interval() : Interval::hull(lo, lo+size-1);
176 }
177
182 static Interval baseSizeSat(T lo, T size) {
183 if (baseSizeOverflows(lo, size)) {
184 return hull(lo, boost::integer_traits<T>::const_max);
185 } else {
186 return baseSize(lo, size);
187 }
188 }
189
191 static Interval whole() {
192 return hull(boost::integer_traits<T>::const_min, boost::integer_traits<T>::const_max);
193 }
194
196 Interval& operator=(const Interval &other) {
197 lo_ = other.lo_;
198 hi_ = other.hi_;
199 return *this;
200 }
201
203 Interval& operator=(T value) {
204 lo_ = hi_ = value;
205 return *this;
206 }
207
212 static bool baseSizeOverflows(T base, T size) {
213 // Warning: This only works when T is unsigned since signed integer overflow is undefined behavior in C++.
214 return base + size < base;
215 }
216
218 T least() const {
219 ASSERT_forbid(isEmpty());
220 return lo_;
221 }
222
224 T greatest() const {
225 ASSERT_forbid(isEmpty());
226 return hi_;
227 }
228
230 bool isEmpty() const { return 1==lo_ && 0==hi_; }
231
233 bool isSingleton() const { return lo_ == hi_; }
234
236 bool isWhole() const { return lo_==boost::integer_traits<T>::const_min && hi_==boost::integer_traits<T>::const_max; }
237
243 bool overlaps(const Interval &other) const {
244 return !intersection(other).isEmpty();
245 }
246 bool isOverlapping(const Interval &other) const {
247 return overlaps(other);
248 }
257 bool contains(const Interval &other) const {
258 return (other.isEmpty() ||
259 (!isEmpty() && least()<=other.least() && greatest()>=other.greatest()));
260 }
261 bool isContaining(const Interval &other) const {
262 return contains(other);
263 }
272 bool isLeftAdjacent(const Interval &right) const {
273 return isEmpty() || right.isEmpty() || (!isWhole() && greatest()+1 == right.least());
274 }
275 bool isRightAdjacent(const Interval &left) const {
276 return isEmpty() || left.isEmpty() || (!left.isWhole() && left.greatest()+1 == least());
277 }
278 bool isAdjacent(const Interval &other) const {
279 return (isEmpty() || other.isEmpty() ||
280 (!isWhole() && greatest()+1 == other.least()) ||
281 (!other.isWhole() && other.greatest()+1 == least()));
282 }
291 bool isLeftOf(const Interval &right) const {
292 return isEmpty() || right.isEmpty() || greatest() < right.least();
293 }
294 bool isRightOf(const Interval &left) const {
295 return isEmpty() || left.isEmpty() || left.greatest() < least();
296 }
302 Value size() const {
303 return isEmpty() ? 0 : hi_ - lo_ + 1;
304 }
305
312 bool operator==(const Interval &other) const {
313 return lo_==other.lo_ && hi_==other.hi_;
314 }
315 bool operator!=(const Interval &other) const {
316 return lo_!=other.lo_ || hi_!=other.hi_;
317 }
325 Interval intersection(const Interval &other) const {
326 if (isEmpty() || other.isEmpty() || greatest()<other.least() || least()>other.greatest())
327 return Interval();
328 return Interval::hull(std::max(least(), other.least()), std::min(greatest(), other.greatest()));
329 }
330 Interval operator&(const Interval &other) const {
331 return intersection(other);
332 }
340 Interval hull(const Interval &other) const {
341 if (isEmpty()) {
342 return other;
343 } else if (other.isEmpty()) {
344 return *this;
345 } else {
346 return Interval::hull(std::min(least(), other.least()), std::max(greatest(), other.greatest()));
347 }
348 }
349
353 Interval hull(T value) const {
354 if (isEmpty()) {
355 return Interval(value);
356 } else {
357 return Interval::hull(std::min(least(), value), std::max(greatest(), value));
358 }
359 }
360
367 std::pair<Interval, Interval> split(T splitPoint) const {
368 if (isEmpty()) {
369 return std::make_pair(Interval(), Interval());
370 } else if (splitPoint < least()) {
371 return std::make_pair(Interval(), *this);
372 } else if (splitPoint < greatest()) {
373 return std::make_pair(Interval::hull(least(), splitPoint), Interval::hull(splitPoint+1, greatest()));
374 } else {
375 return std::make_pair(*this, Interval());
376 }
377 }
378
386 Interval join(const Interval &right) const {
387 if (isEmpty()) {
388 return right;
389 } else if (right.isEmpty()) {
390 return *this;
391 } else {
392 ASSERT_require(greatest()+1 == right.least() && right.least() > greatest());
393 return hull(right);
394 }
395 }
396
403 if (isEmpty() || baseSizeOverflows(least(), n)) {
404 return Interval();
405 } else if (baseSizeOverflows(greatest(), n)) {
406 return hull(least() + n, boost::integer_traits<T>::const_max);
407 } else {
408 return hull(least() + n, greatest() + n);
409 }
410 }
411
412 // These types are needed for BOOST_FOREACH but are not advertised as part of this interface.
413 typedef ConstIterator const_iterator;
414 typedef ConstIterator iterator;
415
424 return isEmpty() ? ConstIterator() : ConstIterator(least(), greatest(), least());
425 }
426
435 return isEmpty() ? ConstIterator() : ++ConstIterator(least(), greatest(), greatest());
436 }
437
439 boost::iterator_range<ConstIterator> values() const {
440 return boost::iterator_range<ConstIterator>(begin(), end());
441 }
442
443 // The following trickery is to allow things like "if (x)" to work but without having an implicit
444 // conversion to bool which would cause no end of other problems. This is fixed in C++11
445private:
446 typedef void(Interval::*unspecified_bool)() const;
447 void this_type_does_not_support_comparisons() const {}
448public:
461 operator unspecified_bool() const {
462 return isEmpty() ? 0 : &Interval::this_type_does_not_support_comparisons;
463 }
464};
465
466} // namespace
467} // namespace
468
469#endif
Bidirectional forward iterator.
Definition Interval.h:75
bool atEnd() const
Predicate to determine if an iterator is at one of its end positions.
Definition Interval.h:96
ConstIterator()
Create an empty iterator.
Definition Interval.h:89
Range of values delimited by endpoints.
Definition Interval.h:31
T greatest() const
Returns upper limit.
Definition Interval.h:224
Interval hull(T value) const
Hull.
Definition Interval.h:353
bool isLeftAdjacent(const Interval &right) const
Adjacency predicate.
Definition Interval.h:272
static Interval baseSize(T lo, T size)
Construct an interval from one endpoint and a size.
Definition Interval.h:173
bool isContaining(const Interval &other) const
Containment predicate.
Definition Interval.h:261
static Interval hull(T v1, T v2)
Construct an interval from two endpoints.
Definition Interval.h:162
Interval()
Constructs an empty interval.
Definition Interval.h:141
ConstIterator end() const
Iterator positioned one past the greatest value.
Definition Interval.h:434
ConstIterator begin() const
Iterator positioned at the least value.
Definition Interval.h:423
bool isOverlapping(const Interval &other) const
True if two intervals overlap.
Definition Interval.h:246
Interval & operator=(T value)
Assignment from a scalar.
Definition Interval.h:203
bool isRightOf(const Interval &left) const
Relative position predicate.
Definition Interval.h:294
bool isWhole() const
True if interval covers entire space.
Definition Interval.h:236
static Interval baseSizeSat(T lo, T size)
Construct an interval from one endpoint and size, and clip overflows.
Definition Interval.h:182
Interval shiftRightSat(Value n) const
Shift interval upward.
Definition Interval.h:402
bool contains(const Interval &other) const
Containment predicate.
Definition Interval.h:257
Interval & operator=(const Interval &other)
Assignment from an interval.
Definition Interval.h:196
Interval(const Interval &other)
Copy-constructs an interval.
Definition Interval.h:144
Value size() const
Size of interval.
Definition Interval.h:302
Interval operator&(const Interval &other) const
Intersection.
Definition Interval.h:330
bool isAdjacent(const Interval &other) const
Adjacency predicate.
Definition Interval.h:278
Interval intersection(const Interval &other) const
Intersection.
Definition Interval.h:325
bool operator!=(const Interval &other) const
Equality test.
Definition Interval.h:315
bool isSingleton() const
True if interval is a singleton.
Definition Interval.h:233
bool isLeftOf(const Interval &right) const
Relative position predicate.
Definition Interval.h:291
bool isEmpty() const
True if interval is empty.
Definition Interval.h:230
T least() const
Returns lower limit.
Definition Interval.h:218
bool isRightAdjacent(const Interval &left) const
Adjacency predicate.
Definition Interval.h:275
Interval join(const Interval &right) const
Creates an interval by joining two adjacent intervals.
Definition Interval.h:386
bool overlaps(const Interval &other) const
True if two intervals overlap.
Definition Interval.h:243
Interval hull(const Interval &other) const
Hull.
Definition Interval.h:340
Interval(T value)
Constructs a singleton interval.
Definition Interval.h:147
std::pair< Interval, Interval > split(T splitPoint) const
Split interval in two.
Definition Interval.h:367
boost::iterator_range< ConstIterator > values() const
Iterator range for values.
Definition Interval.h:439
bool operator==(const Interval &other) const
Equality test.
Definition Interval.h:312
static bool baseSizeOverflows(T base, T size)
Tests whether a base and size overflows.
Definition Interval.h:212
T Value
Types of values in the interval.
Definition Interval.h:34
static Interval whole()
Construct an interval that covers the entire domain.
Definition Interval.h:191
Sawyer support library.