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 tdiff iiv (const T &val) const
00052 { return tdiff(std::upper_bound(r.begin(),r.end(),val)-r.begin())-1; }
00053
00054 void addRemove (T a, T b, tdiff v)
00055 {
00056 tdiff pos1=iiv(a), pos2=iiv(b);
00057 if ((pos1>=0) && (r[pos1]==a)) --pos1;
00058
00059 bool insert_a = (pos1&1)==v;
00060 bool insert_b = (pos2&1)==v;
00061 int rmstart=pos1+1+(insert_a ? 1 : 0);
00062 int rmend =pos2-(insert_b?1:0);
00063
00064 planck_assert((rmend-rmstart)&1,"cannot happen");
00065
00066 if (insert_a && insert_b && (pos1+1>pos2))
00067 {
00068 r.insert(r.begin()+pos1+1,2,a);
00069 r[pos1+2]=b;
00070 }
00071 else
00072 {
00073 if (insert_a) r[pos1+1]=a;
00074 if (insert_b) r[pos2]=b;
00075 r.erase(r.begin()+rmstart,r.begin()+rmend+1);
00076 }
00077 }
00078
00079 static void generalUnion (const rtype &a, const rtype &b,
00080 bool flip_a, bool flip_b, rtype &c)
00081 {
00082 planck_assert((&c!=&a)&&(&c!=&b), "cannot overwrite the rangeset");
00083 c.clear();
00084 bool state_a=flip_a, state_b=flip_b, state_res=state_a||state_b;
00085 tsize ia=0, ea=a.size(), ib=0, eb=b.size();
00086 bool runa = ia!=ea, runb = ib!=eb;
00087 while(runa||runb)
00088 {
00089 bool adv_a=false, adv_b=false;
00090 T val,va=T(),vb=T();
00091 if (runa) va = a[ia];
00092 if (runb) vb = b[ib];
00093 if (runa && (!runb || (va<=vb))) { adv_a=true; val=va; }
00094 if (runb && (!runa || (vb<=va))) { adv_b=true; val=vb; }
00095 if (adv_a) { state_a=!state_a; ++ia; runa = ia!=ea; }
00096 if (adv_b) { state_b=!state_b; ++ib; runb = ib!=eb; }
00097 if ((state_a||state_b)!=state_res)
00098 { c.push_back(val); state_res = !state_res; }
00099 }
00100 }
00101
00102 public:
00103
00104 void clear() { r.clear(); }
00105
00106 void reserve(tsize n) { r.reserve(2*n); }
00107
00108 tsize size() const { return r.size()>>1; }
00109
00110 const rtype &data() const { return r; }
00111
00112
00113 const T &ivbegin (tdiff i) const { return r[2*i]; }
00114
00115 const T &ivend (tdiff i) const { return r[2*i+1]; }
00116
00117 T ivlen (tdiff i) const { return r[2*i+1]-r[2*i]; }
00118
00119
00120
00121 void append(const T &v1, const T &v2)
00122 {
00123 if (v2<=v1) return;
00124 if ((!r.empty()) && (v1<=r.back()))
00125 {
00126 planck_assert (v1>=r[r.size()-2],"bad append operation");
00127 if (v2>r.back()) r.back()=v2;
00128 }
00129 else
00130 { r.push_back(v1); r.push_back(v2); }
00131 }
00132
00133
00134 void append(const T &v)
00135 { append(v,v+1); }
00136
00137
00138
00139 void append (const rangeset &other)
00140 {
00141 for (tsize j=0; j<other.size(); ++j)
00142 append(other.ivbegin(j),other.ivend(j));
00143 }
00144
00145
00146
00147 void add(const T &v1, const T &v2) { addRemove(v1,v2,1); }
00148
00149
00150 void add(const T &v) { addRemove(v,v+1,1); }
00151
00152
00153 void remove(const T &v1, const T &v2) { addRemove(v1,v2,0); }
00154
00155 void remove(const T &v) { addRemove(v,v+1,0); }
00156
00157
00158 void intersect (const T &a, const T &b)
00159 {
00160 tdiff pos1=iiv(a), pos2=iiv(b);
00161 if ((pos2>=0) && (r[pos2]==b)) --pos2;
00162
00163 bool insert_a = (pos1&1)==0;
00164 bool insert_b = (pos2&1)==0;
00165
00166
00167 r.erase(r.begin()+pos2+1,r.end());
00168 if (insert_b) r.push_back(b);
00169
00170
00171 if (insert_a) r[pos1--]=a;
00172 if (pos1>=0)
00173 r.erase(r.begin(),r.begin()+pos1+1);
00174 }
00175
00176
00177 T nval() const
00178 {
00179 T result=T(0);
00180 for (tsize i=0; i<r.size(); i+=2)
00181 result+=r[i+1]-r[i];
00182 return result;
00183 }
00184
00185
00186
00187 void toVector (std::vector<T> &res) const
00188 {
00189 res.clear();
00190 res.reserve(nval());
00191 for (tsize i=0; i<r.size(); i+=2)
00192 for (T m(r[i]); m<r[i+1]; ++m)
00193 res.push_back(m);
00194 }
00195
00196
00197
00198 void unite (const rangeset &other)
00199 {
00200 rtype tmp;
00201 generalUnion (r,other.r,false,false,tmp);
00202 std::swap(r,tmp);
00203 }
00204
00205
00206 void intersect (const rangeset &other)
00207 {
00208 rtype tmp;
00209 generalUnion (r,other.r,true,true,tmp);
00210 std::swap(r,tmp);
00211 }
00212
00213
00214 void subtract (const rangeset &other)
00215 {
00216 rtype tmp;
00217 generalUnion (r,other.r,true,false,tmp);
00218 std::swap(r,tmp);
00219 }
00220
00221
00222 void setToUnion (const rangeset &a, const rangeset &b)
00223 { generalUnion (a.r,b.r,false,false,r); }
00224
00225
00226 void setToIntersection (const rangeset &a, const rangeset &b)
00227 { generalUnion (a.r,b.r,true,true,r); }
00228
00229
00230 void setToDifference (const rangeset &a, const rangeset &b)
00231 { generalUnion (a.r,b.r,true,false,r); }
00232
00233
00234
00235 tdiff findInterval (const T &v) const
00236 {
00237 tdiff res = iiv(v);
00238 return (res&1) ? -1 : res>>1;
00239 }
00240
00241
00242
00243 bool equals (const rangeset &other) const
00244 { return r==other.data(); }
00245
00246
00247
00248 bool containsAll (T a,T b) const
00249 {
00250 tdiff res=iiv(a);
00251 if (res&1) return false;
00252 return (b<=r[res+1]);
00253 }
00254
00255
00256 bool contains (T v) const
00257 { return !(iiv(v)&1); }
00258
00259
00260 bool contains (const rangeset &other) const
00261 {
00262 tsize im=0, em=r.size();
00263 for (tsize i=0; i<other.r.size(); i+=2)
00264 {
00265 T a=other.r[i], b=other.r[i+1];
00266 while ((im!=em) && (r[im+1] < a)) im+=2;
00267 if (im==em) return false;
00268 if ((r[im]>a) || (r[im+1]<b)) return false;
00269 }
00270 return true;
00271 }
00272 };
00273
00274 template<typename T> inline std::ostream &operator<< (std::ostream &os,
00275 const rangeset<T> &rs)
00276 {
00277 os << "{ ";
00278 for (tsize i=0; i<rs.size(); ++i)
00279 os << "["<<rs.ivbegin(i)<<";"<<rs.ivend(i)<<"[ ";
00280 return os << "}";
00281 }
00282
00283 #endif