46inline ptrdiff_t roundUpToEven(ptrdiff_t i) {
return i + (i & 1); }
54 using difference_type = ptrdiff_t;
55 using value_type = uint64_t;
56 using pointer = uint64_t *;
57 using reference = uint64_t &;
60 RangeIter() =
default;
61 explicit RangeIter(uint64_t * p) :
ptr{p} {}
63 friend void swap(RangeIter & a, RangeIter &
b) {
std::swap(a.ptr,
b.ptr); }
66 RangeIter & operator++() {
ptr += 2;
return *
this; }
67 RangeIter & operator--() {
ptr -= 2;
return *
this; }
69 RangeIter operator++(
int) { RangeIter i(*
this);
ptr += 2;
return i; }
70 RangeIter operator--(
int) { RangeIter i(*
this);
ptr -= 2;
return i; }
72 RangeIter
operator+(ptrdiff_t n)
const {
return RangeIter(ptr + 2 * n); }
73 RangeIter
operator-(ptrdiff_t n)
const {
return RangeIter(ptr + 2 * n); }
75 RangeIter &
operator+=(ptrdiff_t n) {
ptr += 2 * n;
return *
this; }
76 RangeIter &
operator-=(ptrdiff_t n) {
ptr -= 2 * n;
return *
this; }
78 friend RangeIter
operator+(ptrdiff_t n, RangeIter
const & i) {
return i + n; }
80 ptrdiff_t
operator-(RangeIter
const & i)
const {
return (ptr - i.ptr) / 2; }
83 bool operator==(RangeIter
const & i)
const {
return ptr == i.ptr; }
84 bool operator!=(RangeIter
const & i)
const {
return ptr != i.ptr; }
85 bool operator<(RangeIter
const & i)
const {
return ptr < i.ptr; }
86 bool operator>(RangeIter
const & i)
const {
return ptr > i.ptr; }
87 bool operator<=(RangeIter
const & i)
const {
return ptr <= i.ptr; }
88 bool operator>=(RangeIter
const & i)
const {
return ptr >= i.ptr; }
92 uint64_t * operator->()
const {
return ptr; }
93 uint64_t & operator[](ptrdiff_t n)
const {
return ptr[2 * n]; }
95 uint64_t *
ptr =
nullptr;
107 insert(std::get<0>(t), std::get<1>(t));
119 if (first <= last - 1) {
120 _insert(first, last);
133 struct Complementor {
136 ~Complementor() {
set.complement(); }
138 Complementor c(*
this);
147 result._intersect(_begin(), _end(), s._begin(), s._end());
158 result._intersect(_beginc(), _endc(), s._beginc(), s._endc());
168 result._intersect(_begin(), _end(), s._beginc(), s._endc());
178 }
else if (s.empty()) {
199 uint64_t
const * a = _begin();
200 uint64_t
const * aend = _end();
201 uint64_t
const *
b = s._begin();
202 uint64_t
const * bend = s._end();
203 int astate = (*a == 0);
204 int bstate = (*
b == 0);
209 int state = astate ^ bstate;
214 result._offset = (state == 0);
216 while (a != aend &&
b != bend) {
217 uint64_t av = *a - 1;
218 uint64_t bv = *
b - 1;
221 bool ainc = (av <= bv);
222 bool binc = (bv <= av);
223 uint64_t minval = ainc ? av : bv;
227 if (state != (astate ^ bstate)) {
228 result._ranges.push_back(minval + 1);
240 if ((aend[-1] == 0) == (bend[-1] == 0)) {
241 result._ranges.push_back(0);
255 if (first <= last - 1) {
256 uint64_t r[2] = {first, last};
257 return _intersectsOne(r, _begin(), _end());
259 uint64_t r[4] = {0, last, first, 0};
260 return _intersectsOne(r, _begin(), _end()) ||
261 _intersectsOne(r + 2, _begin(), _end());
265 if (
empty() || s.empty()) {
268 return _intersects(_begin(), _end(), s._begin(), s._end());
278 if (first <= last - 1) {
279 uint64_t r[2] = {first, last};
280 return !_intersectsOne(r, _beginc(), _endc());
282 uint64_t r[4] = {0, last, first, 0};
283 return !_intersectsOne(r, _beginc(), _endc()) &&
284 !_intersectsOne(r + 2, _beginc(), _endc());
288 if (s.empty() ||
full()) {
291 return !_intersects(_beginc(), _endc(), s._begin(), s._end());
295 if (
empty() || first == last) {
298 if (last <= first - 1) {
299 uint64_t r[2] = {last, first};
300 return !_intersectsOne(r, _begin(), _end());
302 uint64_t r[4] = {0, first, last, 0};
303 return !_intersectsOne(r, _begin(), _end()) &&
304 !_intersectsOne(r + 2, _begin(), _end());
309 for (
auto r = _begin(), e = _end(); r != e; r += 2) {
316 if (
empty() || n == 0) {
318 }
else if (n >= 64) {
325 uint64_t
const m = (
static_cast<uint64_t
>(1) << n) - 1;
326 uint64_t * r =
const_cast<uint64_t *
>(_begin());
327 uint64_t * rend =
const_cast<uint64_t *
>(_end());
330 uint64_t first = r[0] & ~m;
331 uint64_t last = (r[1] +
m) & ~
m;
332 if (r[0] != 0 && first == 0) {
340 for (r += 2; last != 0 && r != rend; r += 2) {
341 uint64_t u = r[0] & ~m;
342 uint64_t v = (r[1] +
m) & ~
m;
362 if (
empty() || i == 1) {
368 uint64_t overflowThreshold =
static_cast<uint64_t
>(-1) / i;
369 auto r = _ranges.
begin();
370 auto rend = _ranges.
end();
371 for (; r < rend; ++r) {
373 if (value > overflowThreshold) {
380 _ranges.
erase(r, rend);
386 if (_ranges.
size() < 2) {
389 if (_ranges.
front() != 0 || _ranges.
back() != 0) {
393 for (
auto i = _ranges.
begin() + 1, e = _ranges.
end() - 1; i != e; ++i) {
401void RangeSet::_insert(uint64_t first, uint64_t last) {
407 uint64_t * r =
const_cast<uint64_t *
>(_begin());
408 uint64_t * rend =
const_cast<uint64_t *
>(_end());
411 uint64_t array[4] = {0, first, last, 0};
412 _ranges.
assign(array + (first == 0), array + (4 - (last == 0)));
413 _offset = (first != 0);
414 }
else if (first >= rend[-2]) {
416 if (first <= rend[-1]) {
418 rend[-1] =
std::max(last - 1, rend[-1] - 1) + 1;
442 [](uint64_t u, uint64_t v) {
443 return u - 1 < v - 1;
463 }
else if (last == 0) {
489 uint64_t
const * bend)
498 if (a[0] > bend[-1] - 1 || a[1] - 1 <
b[0]) {
508 }
else if (a[0] <=
b[0] && a[1] - 1 >= bend[-1] - 1) {
515 uint64_t
const * bmid =
b + roundUpToEven((bend -
b) >> 1);
516 _intersectOne(v, a,
b, bmid);
517 _intersectOne(v, a, bmid, bend);
525 uint64_t
const * aend,
527 uint64_t
const * bend)
539 _intersectOne(v, a,
b, bend);
540 }
else if (
b + 2 == bend) {
541 _intersectOne(v,
b, a, aend);
542 }
else if (a[0] <= bend[-1] - 1 && aend[-1] - 1 >=
b[0]) {
551 uint64_t
const * amid = a + roundUpToEven((aend - a) >> 1);
552 uint64_t
const * bmid =
b + roundUpToEven((bend -
b) >> 1);
553 _intersect(v, a, amid,
b, bmid);
554 _intersect(v, a, amid, bmid, bend);
555 _intersect(v, amid, aend,
b, bmid);
556 _intersect(v, amid, aend, bmid, bend);
560void RangeSet::_intersect(uint64_t
const * a,
561 uint64_t
const * aend,
563 uint64_t
const * bend)
565 if (a == aend ||
b == bend) {
572 _offset = ((*a != 0) || (*
b != 0));
574 _intersect(_ranges, a, aend,
b, bend);
575 if ((aend[-1] != 0) || (bend[-1] != 0)) {
583bool RangeSet::_intersectsOne(uint64_t
const * a,
585 uint64_t
const * bend)
588 if (a[0] > bend[-1] - 1 || a[1] - 1 <
b[0]) {
591 if (
b + 2 == bend || a[0] <=
b[0] || a[1] - 1 >= bend[-1] - 1) {
594 uint64_t
const * bmid =
b + roundUpToEven((bend -
b) >> 1);
595 return _intersectsOne(a,
b, bmid) || _intersectsOne(a, bmid, bend);
600bool RangeSet::_intersects(uint64_t
const * a,
601 uint64_t
const * aend,
603 uint64_t
const * bend)
607 return _intersectsOne(a,
b, bend);
610 return _intersectsOne(
b, a, aend);
612 if (a[0] > bend[-1] - 1 || aend[-1] - 1 <
b[0]) {
615 uint64_t
const * amid = a + roundUpToEven((aend - a) >> 1);
616 uint64_t
const * bmid =
b + roundUpToEven((bend -
b) >> 1);
617 return _intersects(a, amid,
b, bmid) ||
618 _intersects(a, amid, bmid, bend) ||
619 _intersects(amid, aend,
b, bmid) ||
620 _intersects(amid, aend, bmid, bend);
624 os <<
"{\"RangeSet\": [";
626 for (
auto const & t: s) {
631 os << '[' << std::get<0>(t) <<
", " << std::get<1>(t) <<
']';
This file provides a type for representing integer sets.
A RangeSet is a set of unsigned 64 bit integers.
RangeSet intersection(RangeSet const &s) const
intersection returns the intersection of this set and s.
bool intersects(uint64_t u) const
void clear()
clear removes all integers from this set.
bool isValid() const
isValid checks that this RangeSet is in a valid state.
bool isWithin(uint64_t u) const
bool full() const
full checks whether all integers in the universe of range sets, [0, 2^64), are in this set.
bool contains(uint64_t u) const
RangeSet join(RangeSet const &s) const
join returns the union of this set and s.
RangeSet & scale(uint64_t i)
scale multiplies the endpoints of each range in this set by the given integer.
bool empty() const
empty checks whether there are any integers in this set.
RangeSet()=default
The default constructor creates an empty set.
void fill()
fill adds all the unsigned 64 bit integers to this set.
RangeSet difference(RangeSet const &s) const
difference returns the difference between this set and s.
RangeSet & simplify(uint32_t n)
simplify simplifies this range set by "coarsening" its ranges.
uint64_t cardinality() const
cardinality returns the number of integers in this set.
RangeSet symmetricDifference(RangeSet const &s) const
symmetricDifference returns the symmetric difference of this set and s.
daf::base::PropertyList * list
daf::base::PropertySet * set
std::shared_ptr< Image< PixelT > > operator+(Image< PixelT > const &img, ImageSlice< PixelT > const &slc)
Overload operator+()
Image< LhsPixelT > & operator+=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Add lhs to Image rhs (i.e. pixel-by-pixel addition) where types are different.
Image< LhsPixelT > & operator-=(Image< LhsPixelT > &lhs, Image< RhsPixelT > const &rhs)
Subtract lhs from Image rhs (i.e. pixel-by-pixel subtraction) where types are different.
std::shared_ptr< Image< PixelT > > operator-(Image< PixelT > const &img, ImageSlice< PixelT > const &slc)
Overload operator-()
void swap(RangeSet &a, RangeSet &b)
std::ostream & operator<<(std::ostream &, Angle const &)
Angle operator*(double a, Angle const &b)