Changeset 184557e for src/Common
- Timestamp:
- Jul 6, 2018, 5:10:14 PM (6 years ago)
- Branches:
- new-env
- Children:
- 5c14030
- Parents:
- b21c77a
- Location:
- src/Common
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Common/PersistentDisjointSet.h
rb21c77a r184557e 128 128 } 129 129 } 130 131 /// Non-initializing constructor; should call init() before use 132 PersistentDisjointSet( Mode m ) : data(), mode(m) {} 130 133 131 134 PersistentDisjointSet( Mode m, Base&& b ) : data(), mode(m) { … … 291 294 size_type count(Elm i) const { return rerooted().count( i ); } 292 295 293 /// Finds root for element i, assertfs i ispresent296 /// Finds root for element i, undefined behaviour if i is not present 294 297 Elm find(Elm i) const { 295 298 const Base& self = rerooted(); … … 375 378 } 376 379 377 /// Reports all members of a class to `out`; none if i does not exist in map 378 template<typename OutputIterator> 379 void find_class(Elm i, OutputIterator&& out) const { 380 private: 381 /// Removes the children of the tree rooted at `root` as `root_node`, returning a new 382 /// uninitialized node and editing `next_edit` to point toward this new node. 383 static Self* remove_children(Elm root, Node& root_node, Base& base_map, Self* next_edit) { 384 // Invariant: root.next is *always* a pointer to a leaf of the most-recently added 385 // subtree. 386 // 387 // Proof: By induction on height: 388 // * height == 0: root.next == root, trivially true 389 // * added.height < root.height: true by ind. hyp. 390 // * added.height == root.height: no node may have a child the same height, ergo 391 // property holds for added, therefore root. 392 // 393 // Corollary: next of most-recently-added subtree root is previously added subtree 394 395 // remove all subtrees 396 while ( root != root_node.next ) { 397 // find added child 398 auto it = base_map.find( root_node.next ); 399 while ( it->second.parent != root ) it = base_map.find( it->second.parent ); 400 Elm added = it->first; 401 Node& added_node = it->second; 402 403 // unlink subtree and set up previous map as ADDTO new map 404 std::swap( root_node.next, added_node.next ); 405 Self* new_edit = new Self{ BASE }; 406 next_edit->init<AddTo>( new_edit, root, added, false ); // assume unchanged root height 407 next_edit->mode = ADDTO; 408 409 // remove subtree children from map 410 next_edit = remove_children( added, added_node, base_map, new_edit ); 411 412 // remove subtree root from map and set up previous map as ADD to new map 413 base_map.erase( added ); 414 new_edit = new Self{ BASE }; 415 next_edit->init<Add>( new_edit, added ); 416 next_edit->mode = ADD; 417 418 next_edit = new_edit; 419 } 420 421 return next_edit; 422 } 423 424 public: 425 /// Removes all elements of a class given by its root; returns updated map. 426 Self* remove_class(Elm root) { 427 reroot(); 428 429 // remove map from self 430 Base base_map = take_as<Base>(); 431 reset_as_base(); 432 433 // find root node and remove children 434 auto it = base_map.find( root ); 435 assertf(it != base_map.end(), "root node must exist in map"); 436 Self* next_edit = remove_children( root, it->second, base_map, this); 437 438 // root is alone in class, remove from map 439 base_map.erase( root ); 440 Self* ret = new Self{ BASE, std::move(base_map) }; 441 // reinitialize previous node as ADD to new map 442 next_edit->init<Add>( ret, root ); 443 next_edit->mode = ADD; 444 445 return ret; 446 } 447 448 /// Applies `f` to all members of a class containing `i` (undefined behaviour if not present). 449 /// `f` should take members by const reference or copy 450 template<typename F> 451 void apply_to_class(Elm i, F&& f) const { 380 452 const Base& self = rerooted(); 381 382 // skip empty classes383 if ( ! self.count( i ) ) return;384 453 385 454 Elm crnt = i; 386 455 do { 387 *out++ = crnt;456 f( crnt ); 388 457 auto it = self.find( crnt ); 389 458 assertf( it != self.end(), "current node must exist in base" ); -
src/Common/PersistentMap.h
rb21c77a r184557e 114 114 } 115 115 116 /// Non-initializing constructor; should call init() before use 117 PersistentMap( Mode m ) : data(), mode(m) {} 118 116 119 PersistentMap( Mode m, Base&& b ) : data(), mode(m) { 117 120 assertf(m == BASE, "invalid mode"); … … 420 423 } 421 424 } 425 426 /// Applies the function `f` to all elements of the map, returning a pointer to the updated map. 427 /// `f` should take two parameters, `const Key&` and `Val&`, returning option<Val> filled with 428 /// the previous value if mutated, an empty option<Val> otherwise. 429 /// NOTE: when porting to C++17, this should work fine with std::optional 430 template<typename F> 431 Self* apply_to_all(F&& f) { 432 // reset to root and exit early if no change 433 if ( rerooted().empty() ) return this; 434 435 // remove map from self 436 Base base_map = take_as<Base>(); 437 reset_as_base(); 438 439 // apply all edits 440 Self* next_edit = this; 441 for ( auto& entry : base_map ) { 442 auto res = f( entry.first, entry.second ); 443 if ( res ) { 444 // entry has been mutated; reset next_edit node as mutation 445 Self* new_node = new Self{ BASE }; 446 next_edit->init<Ins>( new_node, entry.first, *std::move(res) ); 447 next_edit->mode = UPD; 448 next_edit = new_node; 449 } 450 } 451 452 // set map into final node and return 453 next_edit->init<Base>( std::move(base_map) ); 454 return next_edit; 455 } 456 457 /// Applies the function `f` to all elements of the map. 458 /// `f` should take two parameters, `const Key&` and `const Val&`. 459 template<typename F> 460 void apply_to_all(F&& f) const { 461 for ( const auto& entry : rerooted() ) { f( entry.first, entry.second ); } 462 } 422 463 }; 423 464
Note: See TracChangeset
for help on using the changeset viewer.