![]() |
00001 // Copyright (C) 2002 Johan Hoffman and Anders Logg. 00002 // Licensed under the GNU GPL Version 2. 00003 00004 #ifndef __TABLE_H 00005 #define __TABLE_H 00006 00007 #include <dolfin/dolfin_log.h> 00008 00009 namespace dolfin { 00010 00016 00017 template <class T> class Table { 00018 00019 // Forward declaration of nested classes 00020 class Block; 00021 00022 public: 00023 00024 // Forward declaration of nested classes 00025 class Iterator; 00026 00028 Table(); 00029 00031 ~Table(); 00032 00034 void clear(); 00035 00037 T& create(); 00038 00040 T& create(int& id); 00041 00043 T& add(T x); 00044 00046 T& operator() (int id); 00047 00049 void remove(T& x); 00050 00052 int size() const; 00053 00055 bool empty() const; 00056 00058 template <class X> 00059 friend LogStream & operator<< (LogStream & stream, const Table<X> & table); 00060 00062 Iterator begin() const; 00063 00065 Iterator end() const; 00066 00068 Iterator iterator(int id); 00069 00071 friend class Block; 00072 friend class Iterator; 00073 00079 00080 class Iterator { 00081 public: 00082 00084 Iterator(); 00085 00087 Iterator(const Iterator& it); 00088 00090 Iterator(const Table<T>& table); 00091 00093 Iterator(const Table<T>& table, int id); 00094 00096 int index() const; 00097 00099 Iterator& operator++(); 00100 00102 bool end() const; 00103 00105 bool last() const; 00106 00108 T& operator*() const; 00109 00111 T* operator->() const; 00112 00114 operator T*() const; 00115 00117 T* pointer() const; 00118 00120 void operator=(const Iterator& it); 00121 00123 bool operator==(const Iterator& it) const; 00124 00126 bool operator!=(const Iterator& it) const; 00127 00129 friend class Table<T>; 00130 00131 private: 00132 00133 // The table 00134 const Table<T>* table; 00135 00136 // Current block 00137 Block* block; 00138 00139 // Position in current block 00140 int pos; 00141 00142 // Iterator index, 0,1,2,... 00143 int _index; 00144 00145 // True if we have reached the end of the table 00146 bool at_end; 00147 00148 }; 00149 00150 private: 00151 00152 class Block { 00153 public: 00154 00155 friend class Table<T>; 00156 friend class Iterator; 00157 00158 Block(Block* prev); 00159 ~Block(); 00160 00161 T* pointer(int id); 00162 int position(int id); 00163 bool full(); 00164 int first_pos(); 00165 int next_pos(int start); 00166 T& create(int& id); 00167 bool remove(T& x); 00168 00169 private: 00170 00171 // Pointer to previous and next blocks 00172 Block* prev; 00173 Block* next; 00174 00175 // Data 00176 T* data; 00177 bool* empty; 00178 00179 // Next available position 00180 int pos; 00181 00182 // Number of used elements 00183 int used; 00184 00185 // Number of this block 00186 int number; 00187 00188 }; 00189 00190 // Place iterator at the beginning of the table 00191 void iterator_start(Iterator* it) const; 00192 00193 // Place iterator at the element with given id 00194 void iterator_id(Iterator* it, int id) const; 00195 00196 // Step iterator to the next position in the table 00197 void iterator_step(Iterator* it) const; 00198 00199 //--- Table data --- 00200 00201 // Pointers to first and current blocks 00202 Block* _first_block; 00203 Block* _current_block; 00204 00205 // Number of blocks and size of table 00206 int _blocks; 00207 int _size; 00208 00209 // Number of empty positions before current position 00210 int _empty; 00211 00212 }; 00213 00214 //--------------------------------------------------------------------------- 00215 // Implementation of Table 00216 //--------------------------------------------------------------------------- 00217 template <class T> Table<T>::Table() 00218 { 00219 _first_block = 0; 00220 _current_block = 0; 00221 00222 _blocks = 0; 00223 _size = 0; 00224 _empty = 0; 00225 } 00226 //--------------------------------------------------------------------------- 00227 template <class T> Table<T>::~Table() 00228 { 00229 clear(); 00230 } 00231 //--------------------------------------------------------------------------- 00232 template <class T> void Table<T>::clear() 00233 { 00234 // Delete all blocks 00235 if ( _first_block ) { 00236 00237 Block *b = _first_block; 00238 while ( true ) { 00239 00240 if ( b->prev ) 00241 delete b->prev; 00242 00243 if ( !b->next ) 00244 break; 00245 00246 b = b->next; 00247 00248 } 00249 00250 delete b; 00251 } 00252 00253 _first_block = 0; 00254 _current_block = 0; 00255 00256 _blocks = 0; 00257 _size = 0; 00258 _empty = 0; 00259 } 00260 //--------------------------------------------------------------------------- 00261 template <class T> T& Table<T>::create() 00262 { 00263 int dummy; 00264 T& t = create(&dummy); 00265 return t; 00266 } 00267 //--------------------------------------------------------------------------- 00268 template <class T> T& Table<T>::create(int& id) 00269 { 00270 // Create a new block if there are no blocks 00271 if ( !_first_block ){ 00272 _first_block = new Block(0); 00273 _current_block = _first_block; 00274 _blocks = 1; 00275 } 00276 00277 // Check for empty position 00278 if ( _empty > 0 ) { 00279 for (Block *b = _first_block; b; b = b->next) { 00280 if ( !(b->full()) ) { 00281 _size += 1; 00282 _empty -= 1; 00283 return b->create(id); 00284 } 00285 } 00286 dolfin_error("Unable to find empty position in table."); 00287 } 00288 00289 // Use next available position 00290 if ( !_current_block->full() ) { 00291 _size += 1; 00292 return _current_block->create(id); 00293 } 00294 00295 // Create new block 00296 _current_block = new Block(_current_block); 00297 _size += 1; 00298 _blocks += 1; 00299 00300 return _current_block->create(id); 00301 } 00302 //--------------------------------------------------------------------------- 00303 template <class T> T& Table<T>::add(T x) 00304 { 00305 T& new_x = create(); 00306 new_x = x; 00307 return *new_x; 00308 } 00309 //--------------------------------------------------------------------------- 00310 template <class T> T& Table<T>::operator() (int id) 00311 { 00312 // Check current block 00313 if ( id >= _current_block->number*DOLFIN_BLOCK_SIZE && 00314 id < (_current_block->number+1)*DOLFIN_BLOCK_SIZE ) 00315 return *_current_block->pointer(id); 00316 00317 // Check all blocks 00318 for (Block *b = _first_block;; b = b->next){ 00319 00320 if ( id >= b->number*DOLFIN_BLOCK_SIZE && 00321 id < (b->number+1)*DOLFIN_BLOCK_SIZE ) 00322 return *b->pointer(id); 00323 00324 if ( !b->next ) 00325 break; 00326 00327 } 00328 00329 // No element with given id 00330 dolfin_error("No element in table with given id."); 00331 return *_current_block->data; 00332 } 00333 //--------------------------------------------------------------------------- 00334 template <class T> void Table<T>::remove(T& x) 00335 { 00336 // Check current block 00337 if ( _current_block->remove(x) ) { 00338 _size--; 00339 _empty++; 00340 return; 00341 } 00342 00343 // Check all blocks 00344 for (Block *b = _first_block;; b = b->next) 00345 if ( b->remove(x) ) { 00346 _size--; 00347 _empty++; 00348 return; 00349 } 00350 00351 // Couldn't find the element 00352 dolfin_error("Unable to remove element from table."); 00353 } 00354 //--------------------------------------------------------------------------- 00355 template <class T> int Table<T>::size() const 00356 { 00357 return _size; 00358 } 00359 //--------------------------------------------------------------------------- 00360 template <class T> bool Table<T>::empty() const 00361 { 00362 return _size == 0; 00363 } 00364 //--------------------------------------------------------------------------- 00365 template <class T> LogStream& operator<<(LogStream& stream, const Table<T> &table) 00366 { 00367 stream << "[ Block-linked list of size " << table._size << ". "; 00368 stream << table._blocks*DOLFIN_BLOCK_SIZE << " elements allocated in " 00369 << table._blocks << " blocks.]"; 00370 00371 return stream; 00372 } 00373 //--------------------------------------------------------------------------- 00374 template <class T> typename Table<T>::Iterator Table<T>::begin() const 00375 { 00376 return Iterator(*this); 00377 } 00378 //--------------------------------------------------------------------------- 00379 template <class T> typename Table<T>::Iterator Table<T>::end() const 00380 { 00381 return Iterator(); 00382 } 00383 //--------------------------------------------------------------------------- 00384 template <class T> typename Table<T>::Iterator Table<T>::iterator(int id) 00385 { 00386 return Iterator(*this, id); 00387 } 00388 //--------------------------------------------------------------------------- 00389 template <class T> void Table<T>::iterator_start(Iterator* it) const 00390 { 00391 // Check if the table is empty 00392 if ( _size == 0 ) { 00393 it->at_end = true; 00394 return; 00395 } 00396 00397 // Table is not empty 00398 it->at_end = false; 00399 00400 // Place iterator at the beginning of the table 00401 for (Block *b = _first_block; b; b = b->next) { 00402 00403 int pos = 0; 00404 if ( (pos = b->first_pos()) != -1 ) { 00405 it->block = b; 00406 it->pos = pos; 00407 return; 00408 } 00409 00410 } 00411 00412 // Something strange happened 00413 dolfin_error("Unable to find first element in the table."); 00414 } 00415 //--------------------------------------------------------------------------- 00416 template <class T> void Table<T>::iterator_id(Iterator* it, int id) const 00417 { 00418 it->at_end = false; 00419 00420 // Check current block 00421 if ( id >= _current_block->number*DOLFIN_BLOCK_SIZE && 00422 id < (_current_block->number+1)*DOLFIN_BLOCK_SIZE ) { 00423 it->block = _current_block; 00424 it->pos = _current_block->position(id); 00425 return; 00426 } 00427 00428 // Check all blocks 00429 for (Block *b = _first_block; b; b = b->next) { 00430 00431 if ( id >= b->number*DOLFIN_BLOCK_SIZE && 00432 id < (b->number+1)*DOLFIN_BLOCK_SIZE ) { 00433 it->block = _current_block; 00434 it->pos = _current_block->position(id); 00435 return; 00436 } 00437 00438 } 00439 00440 // No element with given id 00441 dolfin_error("Unable to create iterator for given id."); 00442 } 00443 //--------------------------------------------------------------------------- 00444 template <class T> void Table<T>::iterator_step(Iterator* it) const 00445 { 00446 // Check if the table is empty 00447 if ( _size == 0 ) { 00448 it->at_end = true; 00449 return; 00450 } 00451 00452 // Step to next position 00453 int start = it->pos + 1; 00454 for (Block* b = it->block; b; b = b->next) { 00455 00456 int pos = 0; 00457 if ( (pos = b->next_pos(start)) != -1 ) { 00458 it->block = b; 00459 it->pos = pos; 00460 return; 00461 } 00462 00463 start = 0; 00464 } 00465 00466 // We have reached the end of the table 00467 it->at_end = true; 00468 } 00469 //--------------------------------------------------------------------------- 00470 // Implementation of Table<T>::Iterator 00471 //--------------------------------------------------------------------------- 00472 template <class T> Table<T>::Iterator::Iterator() 00473 { 00474 table = 0; 00475 00476 block = 0; 00477 _index = -1; 00478 pos = 0; 00479 00480 at_end = true; 00481 } 00482 //--------------------------------------------------------------------------- 00483 template <class T> Table<T>::Iterator::Iterator(const Iterator& it) 00484 { 00485 table = it.table; 00486 block = it.block; 00487 pos = it.pos; 00488 _index = it._index; 00489 at_end = it.at_end; 00490 } 00491 //--------------------------------------------------------------------------- 00492 template <class T> Table<T>::Iterator::Iterator(const Table<T>& table) 00493 { 00494 this->table = &table; 00495 table.iterator_start(this); 00496 _index = 0; 00497 } 00498 //--------------------------------------------------------------------------- 00499 template <class T> Table<T>::Iterator::Iterator(const Table<T>& table, int id) 00500 { 00501 this->table = &table; 00502 table.iterator_id(this, id); 00503 _index = id; 00504 } 00505 //--------------------------------------------------------------------------- 00506 template <class T> int Table<T>::Iterator::index() const 00507 { 00508 return _index; 00509 } 00510 //--------------------------------------------------------------------------- 00511 template <class T> typename Table<T>::Iterator& Table<T>::Iterator::operator++() 00512 { 00513 if ( table ) { 00514 table->iterator_step(this); 00515 _index++; 00516 } 00517 return *this; 00518 } 00519 //--------------------------------------------------------------------------- 00520 template <class T> bool Table<T>::Iterator::end() const 00521 { 00522 return at_end; 00523 } 00524 //--------------------------------------------------------------------------- 00525 template <class T> bool Table<T>::Iterator::last() const 00526 { 00527 return _index == (table->size() - 1); 00528 } 00529 //--------------------------------------------------------------------------- 00530 template <class T> T& Table<T>::Iterator::operator*() const 00531 { 00532 return block->data[pos]; 00533 } 00534 //--------------------------------------------------------------------------- 00535 template <class T> T* Table<T>::Iterator::operator->() const 00536 { 00537 return block->data+pos; 00538 } 00539 //--------------------------------------------------------------------------- 00540 template <class T> Table<T>::Iterator::operator T*() const 00541 { 00542 return block->data+pos; 00543 } 00544 //--------------------------------------------------------------------------- 00545 template <class T> T* Table<T>::Iterator::pointer() const 00546 { 00547 return block->data+pos; 00548 } 00549 //--------------------------------------------------------------------------- 00550 template <class T> void Table<T>::Iterator::operator=(const Iterator& it) 00551 { 00552 table = it.table; 00553 block = it.block; 00554 pos = it.pos; 00555 _index = it._index; 00556 at_end = it.at_end; 00557 } 00558 //--------------------------------------------------------------------------- 00559 template <class T> bool Table<T>::Iterator::operator== 00560 (const Iterator& it) const 00561 { 00562 if ( at_end && it.at_end ) 00563 return true; 00564 00565 return table == it.table && block == it.block && pos == it.pos; 00566 } 00567 //--------------------------------------------------------------------------- 00568 template <class T> bool Table<T>::Iterator::operator!= 00569 (const Iterator& it) const 00570 { 00571 return !( *this == it ); 00572 } 00573 //--------------------------------------------------------------------------- 00574 // Implementation of Table<T>::Block 00575 //--------------------------------------------------------------------------- 00576 template <class T> Table<T>::Block::Block(Block* prev) 00577 { 00578 // Set block number 00579 if ( prev ) 00580 number = prev->number + 1; 00581 else 00582 number = 0; 00583 00584 // Link blocks 00585 if ( prev ) 00586 prev->next = this; 00587 this->prev = prev; 00588 next = 0; 00589 00590 // Allocate memory for this block 00591 if ( !(data = new T[DOLFIN_BLOCK_SIZE]) ) 00592 dolfin_error("Out of memory."); 00593 if ( !(empty = new bool[DOLFIN_BLOCK_SIZE]) ) 00594 dolfin_error("Out of memory."); 00595 for (int i=0;i<DOLFIN_BLOCK_SIZE;i++) 00596 empty[i] = true; 00597 pos = 0; 00598 used = 0; 00599 } 00600 //--------------------------------------------------------------------------- 00601 template <class T> Table<T>::Block::~Block() 00602 { 00603 delete [] data; 00604 delete [] empty; 00605 } 00606 //--------------------------------------------------------------------------- 00607 template <class T> T* Table<T>::Block::pointer(int id) 00608 { 00609 id -= number*DOLFIN_BLOCK_SIZE; 00610 00611 if ( id < 0 || id >= DOLFIN_BLOCK_SIZE ) 00612 return 0; 00613 00614 return data + id; 00615 } 00616 //--------------------------------------------------------------------------- 00617 template <class T> int Table<T>::Block::position(int id) 00618 { 00619 return id - number*DOLFIN_BLOCK_SIZE; 00620 } 00621 //--------------------------------------------------------------------------- 00622 template <class T> bool Table<T>::Block::full() 00623 { 00624 return used == DOLFIN_BLOCK_SIZE; 00625 } 00626 //--------------------------------------------------------------------------- 00627 template <class T> int Table<T>::Block::first_pos() 00628 { 00629 for (int i =0 ; i < DOLFIN_BLOCK_SIZE; i++) 00630 if ( !empty[i] ) 00631 return i; 00632 00633 return -1; 00634 } 00635 //--------------------------------------------------------------------------- 00636 template <class T> int Table<T>::Block::next_pos(int start) 00637 { 00638 for (int i = start; i < DOLFIN_BLOCK_SIZE; i++) 00639 if ( !empty[i] ) 00640 return i; 00641 00642 return -1; 00643 } 00644 //--------------------------------------------------------------------------- 00645 template <class T> T& Table<T>::Block::create(int& id) 00646 { 00647 // Check if the table is full 00648 if ( used == DOLFIN_BLOCK_SIZE ) 00649 dolfin_error("Block is full."); 00650 00651 // Check if there is an empty position 00652 if ( used != pos ){ 00653 for (int i = 0; i < DOLFIN_BLOCK_SIZE; i++) 00654 if ( empty[i] ){ 00655 empty[i] = false; 00656 used += 1; 00657 id = number*DOLFIN_BLOCK_SIZE + i; 00658 return data[i]; 00659 } 00660 dolfin_error("Unable to find an empty position."); 00661 } 00662 00663 // Use next available position 00664 empty[pos] = false; 00665 id = number*DOLFIN_BLOCK_SIZE + pos; 00666 pos += 1; 00667 used += 1; 00668 00669 return data[pos-1]; 00670 } 00671 //--------------------------------------------------------------------------- 00672 template <class T> bool Table<T>::Block::remove(T& x) 00673 { 00674 int pos = &x - data; 00675 00676 if ( pos < 0 ) 00677 return false; 00678 00679 if ( pos >= DOLFIN_BLOCK_SIZE ) 00680 return false; 00681 00682 // Mark the position as empty 00683 empty[pos] = true; 00684 used--; 00685 00686 return true; 00687 } 00688 //--------------------------------------------------------------------------- 00689 00690 } 00691 00692 #endif
Documentation automatically generated with Doxygen on 10 Sep 2004.