8#ifndef Sawyer_Interval_H
9#define Sawyer_Interval_H
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>
38#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
40 friend class boost::serialization::access;
43 void serialize(S &s,
const unsigned ) {
44 s & BOOST_SERIALIZATION_NVP(lo_);
45 s & BOOST_SERIALIZATION_NVP(hi_);
49#ifdef SAWYER_HAVE_CEREAL
51 friend class cereal::access;
53 template<
class Archive>
54 void CEREAL_SERIALIZE_FUNCTION_NAME(Archive &archive) {
55 archive(CEREAL_NVP(lo_));
56 archive(CEREAL_NVP(hi_));
74 class ConstIterator:
public boost::iterator_facade<ConstIterator, const Value, boost::bidirectional_traversal_tag,
77 friend class boost::iterator_core_access;
79 T first_, cur_, last_;
82 ConstIterator(T first, T last, T cur): first_(first), cur_(cur), last_(last), atEnd_(
false) {}
101 Value dereference()
const {
102 ASSERT_forbid(
atEnd());
107 if (
atEnd() || other.atEnd())
108 return atEnd() && other.atEnd();
109 return cur_ == other.cur_;
120 ASSERT_require(cur_ == first_);
128 if (cur_ == first_) {
131 ASSERT_require(cur_ == last_);
154 Interval(T lo, T hi): lo_(lo), hi_(hi) {
155 ASSERT_require(lo <= hi);
164 retval.lo_ = std::min(v1, v2);
165 retval.hi_ = std::max(v1, v2);
174 ASSERT_forbid(baseSizeOverflows(lo, size));
183 if (baseSizeOverflows(lo, size)) {
184 return hull(lo, boost::integer_traits<T>::const_max);
186 return baseSize(lo, size);
192 return hull(boost::integer_traits<T>::const_min, boost::integer_traits<T>::const_max);
214 return base + size < base;
219 ASSERT_forbid(isEmpty());
225 ASSERT_forbid(isEmpty());
230 bool isEmpty()
const {
return 1==lo_ && 0==hi_; }
236 bool isWhole()
const {
return lo_==boost::integer_traits<T>::const_min && hi_==boost::integer_traits<T>::const_max; }
244 return !intersection(other).isEmpty();
247 return overlaps(other);
259 (!isEmpty() && least()<=other.
least() && greatest()>=other.
greatest()));
262 return contains(other);
273 return isEmpty() || right.
isEmpty() || (!isWhole() && greatest()+1 == right.
least());
279 return (isEmpty() || other.
isEmpty() ||
280 (!isWhole() && greatest()+1 == other.
least()) ||
292 return isEmpty() || right.
isEmpty() || greatest() < right.
least();
303 return isEmpty() ? 0 : hi_ - lo_ + 1;
313 return lo_==other.lo_ && hi_==other.hi_;
316 return lo_!=other.lo_ || hi_!=other.hi_;
331 return intersection(other);
357 return Interval::hull(std::min(least(), value), std::max(greatest(), value));
367 std::pair<Interval, Interval>
split(T splitPoint)
const {
370 }
else if (splitPoint < least()) {
371 return std::make_pair(
Interval(), *
this);
372 }
else if (splitPoint < greatest()) {
375 return std::make_pair(*
this,
Interval());
392 ASSERT_require(greatest()+1 == right.
least() && right.
least() > greatest());
403 if (isEmpty() || baseSizeOverflows(least(), n)) {
405 }
else if (baseSizeOverflows(greatest(), n)) {
406 return hull(least() + n, boost::integer_traits<T>::const_max);
408 return hull(least() + n, greatest() + n);
413 typedef ConstIterator const_iterator;
414 typedef ConstIterator iterator;
439 boost::iterator_range<ConstIterator>
values()
const {
440 return boost::iterator_range<ConstIterator>(begin(), end());
446 typedef void(
Interval::*unspecified_bool)() const;
447 void this_type_does_not_support_comparisons()
const {}
461 operator unspecified_bool()
const {
462 return isEmpty() ? 0 : &Interval::this_type_does_not_support_comparisons;
Bidirectional forward iterator.
bool atEnd() const
Predicate to determine if an iterator is at one of its end positions.
ConstIterator()
Create an empty iterator.
Range of values delimited by endpoints.
T greatest() const
Returns upper limit.
Interval hull(T value) const
Hull.
bool isLeftAdjacent(const Interval &right) const
Adjacency predicate.
static Interval baseSize(T lo, T size)
Construct an interval from one endpoint and a size.
bool isContaining(const Interval &other) const
Containment predicate.
static Interval hull(T v1, T v2)
Construct an interval from two endpoints.
Interval()
Constructs an empty interval.
ConstIterator end() const
Iterator positioned one past the greatest value.
ConstIterator begin() const
Iterator positioned at the least value.
bool isOverlapping(const Interval &other) const
True if two intervals overlap.
Interval & operator=(T value)
Assignment from a scalar.
bool isRightOf(const Interval &left) const
Relative position predicate.
bool isWhole() const
True if interval covers entire space.
static Interval baseSizeSat(T lo, T size)
Construct an interval from one endpoint and size, and clip overflows.
Interval shiftRightSat(Value n) const
Shift interval upward.
bool contains(const Interval &other) const
Containment predicate.
Interval & operator=(const Interval &other)
Assignment from an interval.
Interval(const Interval &other)
Copy-constructs an interval.
Value size() const
Size of interval.
Interval operator&(const Interval &other) const
Intersection.
bool isAdjacent(const Interval &other) const
Adjacency predicate.
Interval intersection(const Interval &other) const
Intersection.
bool operator!=(const Interval &other) const
Equality test.
bool isSingleton() const
True if interval is a singleton.
bool isLeftOf(const Interval &right) const
Relative position predicate.
bool isEmpty() const
True if interval is empty.
T least() const
Returns lower limit.
bool isRightAdjacent(const Interval &left) const
Adjacency predicate.
Interval join(const Interval &right) const
Creates an interval by joining two adjacent intervals.
bool overlaps(const Interval &other) const
True if two intervals overlap.
Interval hull(const Interval &other) const
Hull.
Interval(T value)
Constructs a singleton interval.
std::pair< Interval, Interval > split(T splitPoint) const
Split interval in two.
boost::iterator_range< ConstIterator > values() const
Iterator range for values.
bool operator==(const Interval &other) const
Equality test.
static bool baseSizeOverflows(T base, T size)
Tests whether a base and size overflows.
T Value
Types of values in the interval.
static Interval whole()
Construct an interval that covers the entire domain.