39 inline 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));
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) {
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;
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) {
394 void 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;
435 [](uint64_t u, uint64_t v) {
436 return u - 1 < v - 1;
456 }
else if (last == 0) {
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);
553 void 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)) {
576 bool 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);
593 bool 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) <<
']';