00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef PLANCK_RANGESET_H
00033 #define PLANCK_RANGESET_H
00034
00035 #include <algorithm>
00036 #include <vector>
00037 #include <utility>
00038 #include <iostream>
00039 #include "datatypes.h"
00040 #include "error_handling.h"
00041
00042
00043 template<typename T> class rangeset
00044 {
00045 private:
00046 typedef std::vector<T> rtype;
00047 typedef typename rtype::iterator iterator;
00048 typedef typename rtype::const_iterator c_iterator;
00049 rtype r;
00050
00051
00052
00053 tdiff iiv (const T &val) const
00054 { return tdiff(std::upper_bound(r.begin(),r.end(),val)-r.begin())-1; }
00055
00056 void addRemove (T a, T b, tdiff v)
00057 {
00058 tdiff pos1=iiv(a), pos2=iiv(b);
00059 if ((pos1>=0) && (r[pos1]==a)) --pos1;
00060
00061 bool insert_a = (pos1&1)==v;
00062 bool insert_b = (pos2&1)==v;
00063 tdiff rmstart=pos1+1+(insert_a ? 1 : 0);
00064 tdiff rmend =pos2-(insert_b ? 1 : 0);
00065
00066 planck_assert((rmend-rmstart)&1,"cannot happen");
00067
00068 if (insert_a && insert_b && (pos1+1>pos2))
00069 {
00070 r.insert(r.begin()+pos1+1,2,a);
00071 r[pos1+2]=b;
00072 }
00073 else
00074 {
00075 if (insert_a) r[pos1+1]=a;
00076 if (insert_b) r[pos2]=b;
00077 r.erase(r.begin()+rmstart,r.begin()+rmend+1);
00078 }
00079 }
00080
00081
00082 static int strategy (tsize sza, tsize szb)
00083 {
00084 const double fct1 = 1.;
00085 const double fct2 = 1.;
00086 tsize slo = sza<szb ? sza : szb,
00087 shi = sza<szb ? szb : sza;
00088 double cost1 = fct1 * (sza+szb);
00089 double cost2 = fct2 * slo * std::max(1,ilog2(shi));
00090 return (cost1<=cost2) ? 1 : (slo==sza) ? 2 : 3;
00091 }
00092
00093 void generalUnion1 (const rangeset &a, const rangeset &b,
00094 bool flip_a, bool flip_b)
00095 {
00096 bool state_a=flip_a, state_b=flip_b, state_res=state_a||state_b;
00097 tsize ia=0, ea=a.r.size(), ib=0, eb=b.r.size();
00098 bool runa = ia!=ea, runb = ib!=eb;
00099 while(runa||runb)
00100 {
00101 T va = runa ? a.r[ia] : T(0),
00102 vb = runb ? b.r[ib] : T(0);
00103 bool adv_a = runa && (!runb || (va<=vb)),
00104 adv_b = runb && (!runa || (vb<=va));
00105 if (adv_a) { state_a=!state_a; ++ia; runa = ia!=ea; }
00106 if (adv_b) { state_b=!state_b; ++ib; runb = ib!=eb; }
00107 if ((state_a||state_b)!=state_res)
00108 { r.push_back(adv_a ? va : vb); state_res = !state_res; }
00109 }
00110 }
00111 void generalUnion2 (const rangeset &a, const rangeset &b,
00112 bool flip_a, bool flip_b)
00113 {
00114 tdiff iva = flip_a ? 0 : -1;
00115 tdiff asz=tdiff(a.r.size()), bsz=tdiff(b.r.size());
00116 while (iva<asz)
00117 {
00118 tdiff ivb = (iva==-1) ? -1 : b.iiv(a.r[iva]);
00119 bool state_b = flip_b^((ivb&1)==0);
00120 if ((iva>-1) && (!state_b)) r.push_back(a.r[iva]);
00121 while((ivb<bsz-1)&&((iva==asz-1)||(b.r[ivb+1]<a.r[iva+1])))
00122 { ++ivb; state_b=!state_b; r.push_back(b.r[ivb]); }
00123 if ((iva<asz-1)&&(!state_b)) r.push_back(a.r[iva+1]);
00124 iva+=2;
00125 }
00126 }
00127 void generalUnion (const rangeset &a, const rangeset &b,
00128 bool flip_a, bool flip_b)
00129 {
00130 planck_assert((this!=&a)&&(this!=&b), "cannot overwrite the rangeset");
00131 if (a.r.empty())
00132 {
00133 if (flip_a) clear(); else *this=b;
00134 return;
00135 }
00136 if (b.r.empty())
00137 {
00138 if (flip_b) clear(); else *this=a;
00139 return;
00140 }
00141
00142 clear();
00143 int strat = strategy (a.nranges(), b.nranges());
00144 (strat==1) ? generalUnion1(a,b,flip_a,flip_b) :
00145 ((strat==2) ? generalUnion2(a,b,flip_a,flip_b)
00146 : generalUnion2(b,a,flip_b,flip_a));
00147 }
00148 void generalXor (const rangeset &a, const rangeset &b)
00149 {
00150 clear();
00151 bool state_a=false, state_b=false, state_res=state_a||state_b;
00152 tsize ia=0, ea=a.r.size(), ib=0, eb=b.r.size();
00153 bool runa = ia!=ea, runb = ib!=eb;
00154 while(runa||runb)
00155 {
00156 T va = runa ? a.r[ia] : T(0),
00157 vb = runb ? b.r[ib] : T(0);
00158 bool adv_a = runa && (!runb || (va<=vb)),
00159 adv_b = runb && (!runa || (vb<=va));
00160 if (adv_a) { state_a=!state_a; ++ia; runa = ia!=ea; }
00161 if (adv_b) { state_b=!state_b; ++ib; runb = ib!=eb; }
00162 if ((state_a^state_b)!=state_res)
00163 { r.push_back(adv_a ? va : vb); state_res = !state_res; }
00164 }
00165 }
00166
00167 static bool generalAllOrNothing1 (const rangeset &a, const rangeset &b,
00168 bool flip_a, bool flip_b)
00169 {
00170 bool state_a=flip_a, state_b=flip_b, state_res=state_a||state_b;
00171 tsize ia=0, ea=a.r.size(), ib=0, eb=b.r.size();
00172 bool runa = ia!=ea, runb = ib!=eb;
00173 while(runa||runb)
00174 {
00175 T va = runa ? a.r[ia] : T(0),
00176 vb = runb ? b.r[ib] : T(0);
00177 bool adv_a = runa && (!runb || (va<=vb)),
00178 adv_b = runb && (!runa || (vb<=va));
00179 if (adv_a) { state_a=!state_a; ++ia; runa = ia!=ea; }
00180 if (adv_b) { state_b=!state_b; ++ib; runb = ib!=eb; }
00181 if ((state_a||state_b)!=state_res)
00182 return false;
00183 }
00184 return true;
00185 }
00186 static bool generalAllOrNothing2 (const rangeset &a, const rangeset &b,
00187 bool flip_a, bool flip_b)
00188 {
00189 tdiff iva = flip_a ? 0 : -1;
00190 tdiff asz=tdiff(a.r.size()), bsz=tdiff(b.r.size());
00191 while (iva<asz)
00192 {
00193 if (iva==-1)
00194 { if ((!flip_b)||(b.r[0]<a.r[0])) return false; }
00195 else if (iva==asz-1)
00196 { if ((!flip_b)||(b.r[bsz-1]>a.r[asz-1])) return false; }
00197 else
00198 {
00199 tdiff ivb=b.iiv(a.r[iva]);
00200 if ((ivb!=bsz-1)&&(b.r[ivb+1]<a.r[iva+1])) return false;
00201 if (flip_b==((ivb&1)==0)) return false;
00202 }
00203 iva+=2;
00204 }
00205 return true;
00206 }
00207 static bool generalAllOrNothing (const rangeset &a, const rangeset &b,
00208 bool flip_a, bool flip_b)
00209 {
00210 if (a.r.empty())
00211 return flip_a ? true : b.r.empty();
00212 if (b.r.empty())
00213 return flip_b ? true : a.r.empty();
00214 int strat = strategy (a.nranges(), b.nranges());
00215 return (strat==1) ? generalAllOrNothing1(a,b,flip_a,flip_b) :
00216 ((strat==2) ? generalAllOrNothing2(a,b,flip_a,flip_b)
00217 : generalAllOrNothing2(b,a,flip_b,flip_a));
00218 }
00219
00220 public:
00221
00222 void clear() { r.clear(); }
00223
00224 void reserve(tsize n) { r.reserve(2*n); }
00225
00226 tsize nranges() const { return r.size()>>1; }
00227 tsize size() const { return nranges(); }
00228 bool empty() const { return r.empty(); }
00229
00230 const rtype &data() const { return r; }
00231 void checkConsistency() const
00232 {
00233 planck_assert((r.size()&1)==0,"invalid number of entries");
00234 for (tsize i=1; i<r.size(); ++i)
00235 planck_assert(r[i]>r[i-1],"inconsistent entries");
00236 }
00237 void setData (const rtype &inp)
00238 {
00239 r=inp;
00240 checkConsistency();
00241 }
00242
00243
00244 const T &ivbegin (tdiff i) const { return r[2*i]; }
00245
00246 const T &ivend (tdiff i) const { return r[2*i+1]; }
00247
00248 T ivlen (tdiff i) const { return r[2*i+1]-r[2*i]; }
00249
00250
00251
00252 void append(const T &v1, const T &v2)
00253 {
00254 if (v2<=v1) return;
00255 if ((!r.empty()) && (v1<=r.back()))
00256 {
00257 planck_assert (v1>=r[r.size()-2],"bad append operation");
00258 if (v2>r.back()) r.back()=v2;
00259 }
00260 else
00261 { r.push_back(v1); r.push_back(v2); }
00262 }
00263
00264
00265 void append(const T &v)
00266 { append(v,v+1); }
00267
00268
00269
00270 void append (const rangeset &other)
00271 {
00272 for (tsize j=0; j<other.nranges(); ++j)
00273 append(other.ivbegin(j),other.ivend(j));
00274 }
00275
00276
00277
00278 void add(const T &v1, const T &v2)
00279 {
00280 if (v2<=v1) return;
00281 if (r.empty() || (v1>=r[r.size()-2])) append(v1,v2);
00282 addRemove(v1,v2,1);
00283 }
00284
00285
00286 void add(const T &v) { add(v,v+1); }
00287
00288
00289 void remove(const T &v1, const T &v2)
00290 {
00291 if (v2<=v1) return;
00292 if (r.empty()) return;
00293 if ((v2<=r[0])||(v1>=r.back())) return;
00294 if ((v1<=r[0]) && (v2>=r.back())) { r.clear(); return; }
00295 addRemove(v1,v2,0);
00296 }
00297
00298 void remove(const T &v) { remove(v,v+1); }
00299
00300
00301 void intersect (const T &a, const T &b)
00302 {
00303 if (r.empty()) return;
00304 if ((b<=r[0]) || (a>=r.back())) { r.clear(); return; }
00305 if ((a<=r[0]) && (b>=r.back())) return;
00306
00307 tdiff pos2=iiv(b);
00308 if ((pos2>=0) && (r[pos2]==b)) --pos2;
00309 bool insert_b = (pos2&1)==0;
00310 r.erase(r.begin()+pos2+1,r.end());
00311 if (insert_b) r.push_back(b);
00312
00313 tdiff pos1=iiv(a);
00314 bool insert_a = (pos1&1)==0;
00315 if (insert_a) r[pos1--]=a;
00316 if (pos1>=0)
00317 r.erase(r.begin(),r.begin()+pos1+1);
00318 }
00319
00320
00321 T nval() const
00322 {
00323 T result=T(0);
00324 for (tsize i=0; i<r.size(); i+=2)
00325 result+=r[i+1]-r[i];
00326 return result;
00327 }
00328
00329
00330
00331 void toVector (std::vector<T> &res) const
00332 {
00333 res.clear();
00334 res.reserve(nval());
00335 for (tsize i=0; i<r.size(); i+=2)
00336 for (T m(r[i]); m<r[i+1]; ++m)
00337 res.push_back(m);
00338 }
00339
00340
00341
00342 std::vector<T> toVector() const
00343 {
00344 std::vector<T> res;
00345 toVector(res);
00346 return res;
00347 }
00348
00349
00350 rangeset op_or (const rangeset &other) const
00351 {
00352 rangeset res;
00353 res.generalUnion (*this,other,false,false);
00354 return res;
00355 }
00356
00357 rangeset op_and (const rangeset &other) const
00358 {
00359 rangeset res;
00360 res.generalUnion (*this,other,true,true);
00361 return res;
00362 }
00363
00364 rangeset op_andnot (const rangeset &other) const
00365 {
00366 rangeset res;
00367 res.generalUnion (*this,other,true,false);
00368 return res;
00369 }
00370
00371
00372 rangeset op_xor (const rangeset &other) const
00373 {
00374 rangeset res;
00375 res.generalXor (*this,other);
00376 return res;
00377 }
00378
00379
00380
00381 tdiff findInterval (const T &v) const
00382 {
00383 tdiff res = iiv(v);
00384 return (res&1) ? -1 : res>>1;
00385 }
00386
00387
00388
00389 bool operator== (const rangeset &other) const
00390 { return r==other.r; }
00391
00392
00393
00394 bool contains (T a,T b) const
00395 {
00396 tdiff res=iiv(a);
00397 if (res&1) return false;
00398 return (b<=r[res+1]);
00399 }
00400
00401
00402 bool contains (T v) const
00403 { return !(iiv(v)&1); }
00404
00405
00406 bool contains (const rangeset &other) const
00407 { return generalAllOrNothing(*this,other,false,true); }
00408
00409
00410 bool overlaps (T a,T b) const
00411 {
00412 tdiff res=iiv(a);
00413 if ((res&1)==0) return true;
00414 if (res==tdiff(r.size())-1) return false;
00415 return (r[res+1]<b);
00416 }
00417
00418
00419 bool overlaps (const rangeset &other) const
00420 { return !generalAllOrNothing(*this,other,true,true); }
00421 };
00422
00423 template<typename T> inline std::ostream &operator<< (std::ostream &os,
00424 const rangeset<T> &rs)
00425 {
00426 os << "{ ";
00427 for (tsize i=0; i<rs.nranges(); ++i)
00428 os << "["<<rs.ivbegin(i)<<";"<<rs.ivend(i)<<"[ ";
00429 return os << "}";
00430 }
00431
00432 #endif