00001 //---------------------------------------------------------------------------- 00002 /** @file VCList.cpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #include "VCList.hpp" 00007 #include "ChangeLog.hpp" 00008 00009 using namespace benzene; 00010 00011 //---------------------------------------------------------------------------- 00012 00013 VCList::VCList(HexPoint x, HexPoint y, unsigned int soft) 00014 : m_x(x), m_y(y), 00015 m_softlimit(soft), 00016 m_vcs(), 00017 m_dirty_intersection(false), 00018 m_dirty_union(true) 00019 { 00020 m_soft_intersection.set(); 00021 m_hard_intersection.set(); 00022 } 00023 00024 //---------------------------------------------------------------------------- 00025 00026 std::string VCList::dump() const 00027 { 00028 int i=0; 00029 std::ostringstream os; 00030 const_iterator it, end = m_vcs.end(); 00031 for (it = m_vcs.begin(); it != end; ++it) { 00032 os << i++ << ": "; 00033 os << *it; 00034 os << std::endl; 00035 } 00036 return os.str(); 00037 } 00038 00039 //---------------------------------------------------------------------------- 00040 00041 bool VCList::isSupersetOfAny(const bitset_t& bs) const 00042 { 00043 for (const_iterator it = m_vcs.begin(); it != m_vcs.end(); ++it) 00044 if (BitsetUtil::IsSubsetOf(it->carrier(), bs)) 00045 return true; 00046 return false; 00047 } 00048 00049 bool VCList::isSubsetOfAny(const bitset_t& bs) const 00050 { 00051 for (const_iterator it = m_vcs.begin(); it != m_vcs.end(); ++it) 00052 if (BitsetUtil::IsSubsetOf(bs, it->carrier())) 00053 return true; 00054 return false; 00055 } 00056 00057 int VCList::removeSuperSetsOf(const bitset_t& bs, ChangeLog<VC>* log, 00058 bool dirty_intersections) 00059 { 00060 int count = 0; 00061 for (iterator it = m_vcs.begin(); it != m_vcs.end(); ) 00062 { 00063 if (BitsetUtil::IsSubsetOf(bs, it->carrier())) 00064 { 00065 if (log) log->push(ChangeLog<VC>::REMOVE, *it); 00066 it = m_vcs.erase(it); 00067 count++; 00068 } 00069 else 00070 ++it; 00071 } 00072 if (count) 00073 { 00074 dirty_list_unions(); 00075 if (dirty_intersections) 00076 dirty_list_intersections(); 00077 } 00078 return count; 00079 } 00080 00081 //---------------------------------------------------------------------------- 00082 00083 void VCList::simple_add(const VC& vc) 00084 { 00085 HexAssert((vc.x() == getX() && vc.y() == getY()) || 00086 (vc.x() == getY() && vc.y() == getX())); 00087 00088 iterator it; 00089 unsigned count = 0; 00090 for (it = m_vcs.begin(); it != m_vcs.end(); ++it, ++count) { 00091 if (*it > vc) 00092 break; 00093 } 00094 it = m_vcs.insert(it, vc); 00095 00096 // update unions/intersections 00097 dirty_list_unions(); 00098 if (count < m_softlimit) m_soft_intersection &= vc.carrier(); 00099 m_hard_intersection &= vc.carrier(); 00100 } 00101 00102 VCList::AddResult VCList::add(const VC& vc, ChangeLog<VC>* log) 00103 { 00104 HexAssert((vc.x() == getX() && vc.y() == getY()) || 00105 (vc.x() == getY() && vc.y() == getX())); 00106 00107 unsigned count = 0; 00108 iterator it = m_vcs.begin(); 00109 for (; it != m_vcs.end(); ++it, ++count) 00110 { 00111 if (*it > vc) 00112 break; 00113 00114 if ((*it).isSubsetOf(vc)) 00115 return ADD_FAILED; 00116 } 00117 00118 if (log) log->push(ChangeLog<VC>::ADD, vc); 00119 it = m_vcs.insert(it, vc); 00120 00121 // update unions/intersections 00122 dirty_list_unions(); 00123 if (count < m_softlimit) m_soft_intersection &= vc.carrier(); 00124 m_hard_intersection &= vc.carrier(); 00125 00126 // remove supersets of vc 00127 for (++it; it != m_vcs.end(); ) 00128 { 00129 if (vc.isSubsetOf(*it)) 00130 { 00131 if (log) log->push(ChangeLog<VC>::REMOVE, *it); 00132 it = m_vcs.erase(it); 00133 00134 } else { 00135 ++it; 00136 } 00137 } 00138 00139 return (count < m_softlimit) ? 00140 ADDED_INSIDE_SOFT_LIMIT: 00141 ADDED_INSIDE_HARD_LIMIT; 00142 } 00143 00144 int VCList::add(const VCList& other, ChangeLog<VC>* log) 00145 { 00146 int count = 0; 00147 for (const_iterator it = other.begin(); it != other.end(); ++it) 00148 { 00149 VC v(getX(), getY(), it->key(), it->carrier(), it->rule()); 00150 v.setProcessed(false); 00151 if (this->add(v, log)) 00152 count++; 00153 } 00154 return count; 00155 } 00156 00157 //---------------------------------------------------------------------------- 00158 00159 VCList::iterator VCList::remove(iterator it, ChangeLog<VC>* log) 00160 { 00161 if (log) log->push(ChangeLog<VC>::REMOVE, *it); 00162 it = m_vcs.erase(it); 00163 00164 dirty_list_unions(); 00165 dirty_list_intersections(); 00166 return it; 00167 } 00168 00169 bool VCList::remove(const VC& vc, ChangeLog<VC>* log) 00170 { 00171 iterator it = find(vc); 00172 if (it == end()) 00173 return false; 00174 00175 remove(it, log); 00176 return true; 00177 } 00178 00179 //---------------------------------------------------------------------------- 00180 00181 VCList::const_iterator VCList::find(const VC& vc, 00182 const const_iterator& b, 00183 const const_iterator& e) const 00184 { 00185 const_iterator it = b; 00186 for (; it != e; ++it) { 00187 if (vc == *it) // @todo check size for speedup! 00188 break; 00189 } 00190 return it; 00191 } 00192 00193 VCList::const_iterator VCList::find(const VC& vc) const 00194 { 00195 return find(vc, begin(), end()); 00196 } 00197 00198 VCList::iterator VCList::find(const VC& vc, 00199 const iterator& b, 00200 const iterator& e) 00201 { 00202 iterator it = b; 00203 for (; it != e; ++it) { 00204 if (vc == *it) 00205 break; 00206 } 00207 return it; 00208 } 00209 00210 VCList::iterator VCList::find(const VC& vc) 00211 { 00212 return find(vc, begin(), end()); 00213 } 00214 00215 //---------------------------------------------------------------------------- 00216 00217 void VCList::computeUnions() const 00218 { 00219 bitset_t inter; 00220 inter.set(); 00221 m_union.reset(); 00222 m_greedy_union.reset(); 00223 00224 const_iterator cur = m_vcs.begin(); 00225 const_iterator end = m_vcs.end(); 00226 for (; cur!=end; ++cur) { 00227 m_union |= cur->carrier(); 00228 bitset_t c = inter & cur->carrier(); 00229 if (inter != c) { 00230 m_greedy_union |= cur->carrier(); 00231 inter = c; 00232 } 00233 } 00234 m_dirty_union = false; 00235 } 00236 00237 bitset_t VCList::getUnion() const 00238 { 00239 if (m_dirty_union) { 00240 computeUnions(); 00241 } 00242 return m_union; 00243 } 00244 00245 bitset_t VCList::getGreedyUnion() const 00246 { 00247 if (m_dirty_union) { 00248 computeUnions(); 00249 } 00250 return m_greedy_union; 00251 } 00252 00253 //---------------------------------------------------------------------------- 00254 00255 void VCList::computeIntersections() const 00256 { 00257 m_soft_intersection.set(); 00258 const_iterator cur = m_vcs.begin(); 00259 const_iterator end = m_vcs.end(); 00260 00261 // @todo abort loops early if intersection is empty? 00262 for (int count=0; count<softlimit() && cur!=end; ++cur, ++count) { 00263 m_soft_intersection &= cur->carrier(); 00264 } 00265 m_hard_intersection = m_soft_intersection; 00266 00267 for (; cur != end; ++cur) { 00268 m_hard_intersection &= cur->carrier(); 00269 } 00270 00271 m_dirty_intersection = false; 00272 } 00273 00274 bitset_t VCList::softIntersection() const 00275 { 00276 if (m_dirty_intersection) { 00277 computeIntersections(); 00278 } 00279 return m_soft_intersection; 00280 } 00281 00282 bitset_t VCList::hardIntersection() const 00283 { 00284 if (m_dirty_intersection) { 00285 computeIntersections(); 00286 } 00287 return m_hard_intersection; 00288 } 00289 00290 //---------------------------------------------------------------------------- 00291 00292 int VCList::removeAllContaining(HexPoint cell, std::list<VC>& out, 00293 ChangeLog<VC>* log) 00294 { 00295 if (!getUnion().test(cell)) 00296 return 0; 00297 00298 int count = 0; 00299 for (iterator it = m_vcs.begin(); it != m_vcs.end(); ) { 00300 if (it->carrier().test(cell)) { 00301 out.push_back(*it); 00302 if (log) log->push(ChangeLog<VC>::REMOVE, *it); 00303 it = m_vcs.erase(it); 00304 ++count; 00305 } else { 00306 ++it; 00307 } 00308 } 00309 00310 if (count) { 00311 dirty_list_unions(); 00312 dirty_list_intersections(); 00313 } 00314 return count; 00315 } 00316 00317 int VCList::removeAllContaining(const bitset_t& b, std::list<VC>& out, 00318 ChangeLog<VC>* log) 00319 { 00320 if ((getUnion() & b).none()) 00321 return 0; 00322 00323 int count = 0; 00324 for (iterator it = m_vcs.begin(); it != m_vcs.end(); ) { 00325 if ((it->carrier() & b).any()) { 00326 out.push_back(*it); 00327 if (log) log->push(ChangeLog<VC>::REMOVE, *it); 00328 it = m_vcs.erase(it); 00329 ++count; 00330 } else { 00331 ++it; 00332 } 00333 } 00334 00335 if (count) { 00336 dirty_list_unions(); 00337 dirty_list_intersections(); 00338 } 00339 return count; 00340 } 00341 00342 int VCList::removeAllContaining(const bitset_t& b, ChangeLog<VC>* log) 00343 { 00344 if ((getUnion() & b).none()) 00345 return 0; 00346 00347 int count = 0; 00348 for (iterator it = m_vcs.begin(); it != m_vcs.end(); ) { 00349 if ((it->carrier() & b).any()) { 00350 if (log) log->push(ChangeLog<VC>::REMOVE, *it); 00351 it = m_vcs.erase(it); 00352 ++count; 00353 } else { 00354 ++it; 00355 } 00356 } 00357 00358 if (count) { 00359 dirty_list_unions(); 00360 dirty_list_intersections(); 00361 } 00362 return count; 00363 } 00364 00365 //---------------------------------------------------------------------------- 00366 00367 bool VCList::operator==(const VCList& other) const 00368 { 00369 if (m_softlimit != other.m_softlimit) 00370 return false; 00371 if (size() != other.size()) 00372 return false; 00373 00374 const_iterator us = begin(); 00375 const_iterator them = other.begin(); 00376 while (us != end()) { 00377 if (*us != *them) return false; 00378 if (us->processed() != them->processed()) return false; 00379 ++us; 00380 ++them; 00381 } 00382 return true; 00383 } 00384 00385 bool VCList::operator!=(const VCList& other) const 00386 { 00387 if (size() != other.size()) 00388 return true; 00389 00390 const_iterator us = begin(); 00391 const_iterator them = other.begin(); 00392 while (us != end()) { 00393 if (*us != *them) return true; 00394 if (us->processed() != them->processed()) return true; 00395 ++us; 00396 ++them; 00397 } 00398 return false; 00399 } 00400 00401 //----------------------------------------------------------------------------