39inline ptrdiff_t roundUpToEven(ptrdiff_t i) {
return i + (i & 1); }
47 using difference_type = ptrdiff_t;
48 using value_type = uint64_t;
49 using pointer = uint64_t *;
50 using reference = uint64_t &;
53 RangeIter() =
default;
54 explicit RangeIter(uint64_t * p) :
ptr{p} {}
59 RangeIter & operator++() {
ptr += 2;
return *
this; }
60 RangeIter & operator--() {
ptr -= 2;
return *
this; }
62 RangeIter operator++(
int) { RangeIter i(*
this);
ptr += 2;
return i; }
63 RangeIter operator--(
int) { RangeIter i(*
this);
ptr -= 2;
return i; }
65 RangeIter
operator+(ptrdiff_t n)
const {
return RangeIter(
ptr + 2 * n); }
66 RangeIter
operator-(ptrdiff_t n)
const {
return RangeIter(
ptr + 2 * n); }
68 RangeIter &
operator+=(ptrdiff_t n) {
ptr += 2 * n;
return *
this; }
69 RangeIter &
operator-=(ptrdiff_t n) {
ptr -= 2 * n;
return *
this; }
71 friend RangeIter
operator+(ptrdiff_t n, RangeIter
const & i) {
return i + n; }
73 ptrdiff_t
operator-(RangeIter
const & i)
const {
return (
ptr - i.ptr) / 2; }
76 bool operator==(RangeIter
const & i)
const {
return ptr == i.ptr; }
77 bool operator!=(RangeIter
const & i)
const {
return ptr != i.ptr; }
78 bool operator<(RangeIter
const & i)
const {
return ptr < i.ptr; }
79 bool operator>(RangeIter
const & i)
const {
return ptr > i.ptr; }
80 bool operator<=(RangeIter
const & i)
const {
return ptr <= i.ptr; }
81 bool operator>=(RangeIter
const & i)
const {
return ptr >= i.ptr; }
85 uint64_t * operator->()
const {
return ptr; }
86 uint64_t & operator[](ptrdiff_t n)
const {
return ptr[2 * n]; }
88 uint64_t *
ptr =
nullptr;
100 insert(std::get<0>(t), std::get<1>(t));
111 _ranges.reserve(_ranges.size() + 2);
112 if (
first <= last - 1) {
113 _insert(
first, last);
126 struct Complementor {
129 ~Complementor() {
set.complement(); }
131 Complementor c(*
this);
140 result._intersect(_begin(), _end(), s._begin(), s._end());
151 result._intersect(_beginc(), _endc(), s._beginc(), s._endc());
161 result._intersect(_begin(), _end(), s._beginc(), s._endc());
171 }
else if (s.
empty()) {
192 uint64_t
const *
a = _begin();
193 uint64_t
const * aend = _end();
194 uint64_t
const *
b = s._begin();
195 uint64_t
const * bend = s._end();
196 int astate = (*
a == 0);
197 int bstate = (*
b == 0);
202 int state = astate ^ bstate;
207 result._offset = (state == 0);
209 while (
a != aend &&
b != bend) {
210 uint64_t av = *
a - 1;
211 uint64_t bv = *
b - 1;
214 bool ainc = (av <= bv);
215 bool binc = (bv <= av);
216 uint64_t minval = ainc ? av : bv;
220 if (state != (astate ^ bstate)) {
221 result._ranges.push_back(minval + 1);
233 if ((aend[-1] == 0) == (bend[-1] == 0)) {
234 result._ranges.push_back(0);
248 if (
first <= last - 1) {
249 uint64_t r[2] = {
first, last};
250 return _intersectsOne(r, _begin(), _end());
252 uint64_t r[4] = {0, last,
first, 0};
253 return _intersectsOne(r, _begin(), _end()) ||
254 _intersectsOne(r + 2, _begin(), _end());
261 return _intersects(_begin(), _end(), s._begin(), s._end());
271 if (
first <= last - 1) {
272 uint64_t r[2] = {
first, last};
273 return !_intersectsOne(r, _beginc(), _endc());
275 uint64_t r[4] = {0, last,
first, 0};
276 return !_intersectsOne(r, _beginc(), _endc()) &&
277 !_intersectsOne(r + 2, _beginc(), _endc());
284 return !_intersects(_beginc(), _endc(), s._begin(), s._end());
291 if (last <=
first - 1) {
292 uint64_t r[2] = {last,
first};
293 return !_intersectsOne(r, _begin(), _end());
295 uint64_t r[4] = {0,
first, last, 0};
296 return !_intersectsOne(r, _begin(), _end()) &&
297 !_intersectsOne(r + 2, _begin(), _end());
302 for (
auto r = _begin(), e = _end(); r != e; r += 2) {
309 if (
empty() || n == 0) {
311 }
else if (n >= 64) {
318 uint64_t
const m = (
static_cast<uint64_t
>(1) << n) - 1;
319 uint64_t * r =
const_cast<uint64_t *
>(_begin());
320 uint64_t * rend =
const_cast<uint64_t *
>(_end());
323 uint64_t
first = r[0] & ~m;
324 uint64_t last = (r[1] +
m) & ~
m;
325 if (r[0] != 0 &&
first == 0) {
333 for (r += 2; last != 0 && r != rend; r += 2) {
334 uint64_t u = r[0] & ~m;
335 uint64_t v = (r[1] +
m) & ~
m;
350 _ranges.erase(_ranges.begin() + (out - _ranges.data()), _ranges.end());
355 if (
empty() || i == 1) {
361 uint64_t overflowThreshold =
static_cast<uint64_t
>(-1) / i;
362 auto r = _ranges.begin();
363 auto rend = _ranges.end();
364 for (; r < rend; ++r) {
366 if (value > overflowThreshold) {
373 _ranges.erase(r, rend);
379 if (_ranges.size() < 2) {
382 if (_ranges.front() != 0 || _ranges.back() != 0) {
386 for (
auto i = _ranges.begin() + 1, e = _ranges.end() - 1; i != e; ++i) {
394void RangeSet::_insert(uint64_t
first, uint64_t last) {
400 uint64_t * r =
const_cast<uint64_t *
>(_begin());
401 uint64_t * rend =
const_cast<uint64_t *
>(_end());
404 uint64_t array[4] = {0,
first, last, 0};
405 _ranges.assign(array + (
first == 0), array + (4 - (last == 0)));
406 _offset = (
first != 0);
407 }
else if (
first >= rend[-2]) {
409 if (
first <= rend[-1]) {
411 rend[-1] =
std::max(last - 1, rend[-1] - 1) + 1;
418 _ranges.push_back(last);
420 _ranges.push_back(0);
435 [](uint64_t u, uint64_t v) {
436 return u - 1 < v - 1;
449 _ranges.insert(_ranges.begin() + (r - _ranges.data()), last);
453 _ranges.erase(_ranges.begin() + 1,
454 _ranges.begin() + (
b - _ranges.data()));
456 }
else if (last == 0) {
459 _ranges.erase(_ranges.begin() + (
a - _ranges.data()),
463 _ranges.insert(_ranges.begin() + (
a - _ranges.data()),
470 _ranges.erase(_ranges.begin() + (
a - _ranges.data()),
471 _ranges.begin() + (
b - _ranges.data()));
482 uint64_t
const * bend)
491 if (
a[0] > bend[-1] - 1 ||
a[1] - 1 <
b[0]) {
501 }
else if (
a[0] <=
b[0] &&
a[1] - 1 >= bend[-1] - 1) {
508 uint64_t
const * bmid =
b + roundUpToEven((bend -
b) >> 1);
509 _intersectOne(v,
a,
b, bmid);
510 _intersectOne(v,
a, bmid, bend);
518 uint64_t
const * aend,
520 uint64_t
const * bend)
532 _intersectOne(v,
a,
b, bend);
533 }
else if (
b + 2 == bend) {
534 _intersectOne(v,
b,
a, aend);
535 }
else if (
a[0] <= bend[-1] - 1 && aend[-1] - 1 >=
b[0]) {
544 uint64_t
const * amid =
a + roundUpToEven((aend -
a) >> 1);
545 uint64_t
const * bmid =
b + roundUpToEven((bend -
b) >> 1);
546 _intersect(v,
a, amid,
b, bmid);
547 _intersect(v,
a, amid, bmid, bend);
548 _intersect(v, amid, aend,
b, bmid);
549 _intersect(v, amid, aend, bmid, bend);
553void RangeSet::_intersect(uint64_t
const *
a,
554 uint64_t
const * aend,
556 uint64_t
const * bend)
558 if (
a == aend ||
b == bend) {
565 _offset = ((*
a != 0) || (*
b != 0));
567 _intersect(_ranges,
a, aend,
b, bend);
568 if ((aend[-1] != 0) || (bend[-1] != 0)) {
569 _ranges.push_back(0);
576bool RangeSet::_intersectsOne(uint64_t
const *
a,
578 uint64_t
const * bend)
581 if (
a[0] > bend[-1] - 1 ||
a[1] - 1 <
b[0]) {
584 if (
b + 2 == bend ||
a[0] <=
b[0] ||
a[1] - 1 >= bend[-1] - 1) {
587 uint64_t
const * bmid =
b + roundUpToEven((bend -
b) >> 1);
588 return _intersectsOne(
a,
b, bmid) || _intersectsOne(
a, bmid, bend);
593bool RangeSet::_intersects(uint64_t
const *
a,
594 uint64_t
const * aend,
596 uint64_t
const * bend)
600 return _intersectsOne(
a,
b, bend);
603 return _intersectsOne(
b,
a, aend);
605 if (
a[0] > bend[-1] - 1 || aend[-1] - 1 <
b[0]) {
608 uint64_t
const * amid =
a + roundUpToEven((aend -
a) >> 1);
609 uint64_t
const * bmid =
b + roundUpToEven((bend -
b) >> 1);
610 return _intersects(
a, amid,
b, bmid) ||
611 _intersects(
a, amid, bmid, bend) ||
612 _intersects(amid, aend,
b, bmid) ||
613 _intersects(amid, aend, bmid, bend);
617 os <<
"{\"RangeSet\": [";
619 for (
auto const & t: s) {
624 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)
A base class for image defects.