Blender V2.61 - r43446
|
00001 #ifndef GIM_HASH_TABLE_H_INCLUDED 00002 #define GIM_HASH_TABLE_H_INCLUDED 00003 00006 /* 00007 ----------------------------------------------------------------------------- 00008 This source file is part of GIMPACT Library. 00009 00010 For the latest info, see http://gimpact.sourceforge.net/ 00011 00012 Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. 00013 email: projectileman@yahoo.com 00014 00015 This library is free software; you can redistribute it and/or 00016 modify it under the terms of EITHER: 00017 (1) The GNU Lesser General Public License as published by the Free 00018 Software Foundation; either version 2.1 of the License, or (at 00019 your option) any later version. The text of the GNU Lesser 00020 General Public License is included with this library in the 00021 file GIMPACT-LICENSE-LGPL.TXT. 00022 (2) The BSD-style license that is included with this library in 00023 the file GIMPACT-LICENSE-BSD.TXT. 00024 (3) The zlib/libpng license that is included with this library in 00025 the file GIMPACT-LICENSE-ZLIB.TXT. 00026 00027 This library is distributed in the hope that it will be useful, 00028 but WITHOUT ANY WARRANTY; without even the implied warranty of 00029 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files 00030 GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. 00031 00032 ----------------------------------------------------------------------------- 00033 */ 00034 00035 #include "gim_radixsort.h" 00036 00037 00038 #define GIM_INVALID_HASH 0xffffffff //!< A very very high value 00039 #define GIM_DEFAULT_HASH_TABLE_SIZE 380 00040 #define GIM_DEFAULT_HASH_TABLE_NODE_SIZE 4 00041 #define GIM_HASH_TABLE_GROW_FACTOR 2 00042 00043 #define GIM_MIN_RADIX_SORT_SIZE 860 //!< calibrated on a PIII 00044 00045 template<typename T> 00046 struct GIM_HASH_TABLE_NODE 00047 { 00048 GUINT m_key; 00049 T m_data; 00050 GIM_HASH_TABLE_NODE() 00051 { 00052 } 00053 00054 GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE & value) 00055 { 00056 m_key = value.m_key; 00057 m_data = value.m_data; 00058 } 00059 00060 GIM_HASH_TABLE_NODE(GUINT key, const T & data) 00061 { 00062 m_key = key; 00063 m_data = data; 00064 } 00065 00066 bool operator <(const GIM_HASH_TABLE_NODE<T> & other) const 00067 { 00069 if(m_key < other.m_key) return true; 00070 return false; 00071 } 00072 00073 bool operator >(const GIM_HASH_TABLE_NODE<T> & other) const 00074 { 00076 if(m_key > other.m_key) return true; 00077 return false; 00078 } 00079 00080 bool operator ==(const GIM_HASH_TABLE_NODE<T> & other) const 00081 { 00083 if(m_key == other.m_key) return true; 00084 return false; 00085 } 00086 }; 00087 00089 class GIM_HASH_NODE_GET_KEY 00090 { 00091 public: 00092 template<class T> 00093 inline GUINT operator()( const T& a) 00094 { 00095 return a.m_key; 00096 } 00097 }; 00098 00099 00100 00102 class GIM_HASH_NODE_CMP_KEY_MACRO 00103 { 00104 public: 00105 template<class T> 00106 inline int operator() ( const T& a, GUINT key) 00107 { 00108 return ((int)(a.m_key - key)); 00109 } 00110 }; 00111 00113 class GIM_HASH_NODE_CMP_MACRO 00114 { 00115 public: 00116 template<class T> 00117 inline int operator() ( const T& a, const T& b ) 00118 { 00119 return ((int)(a.m_key - b.m_key)); 00120 } 00121 }; 00122 00123 00124 00125 00126 00128 00131 template<typename T> 00132 void gim_sort_hash_node_array(T * array, GUINT array_count) 00133 { 00134 if(array_count<GIM_MIN_RADIX_SORT_SIZE) 00135 { 00136 gim_heap_sort(array,array_count,GIM_HASH_NODE_CMP_MACRO()); 00137 } 00138 else 00139 { 00140 memcopy_elements_func cmpfunc; 00141 gim_radix_sort(array,array_count,GIM_HASH_NODE_GET_KEY(),cmpfunc); 00142 } 00143 } 00144 00145 00146 00147 00148 00149 00150 // Note: assumes long is at least 32 bits. 00151 #define GIM_NUM_PRIME 28 00152 00153 static const GUINT gim_prime_list[GIM_NUM_PRIME] = 00154 { 00155 53ul, 97ul, 193ul, 389ul, 769ul, 00156 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, 00157 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, 00158 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, 00159 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 00160 1610612741ul, 3221225473ul, 4294967291ul 00161 }; 00162 00163 inline GUINT gim_next_prime(GUINT number) 00164 { 00165 //Find nearest upper prime 00166 GUINT result_ind = 0; 00167 gim_binary_search(gim_prime_list,0,(GIM_NUM_PRIME-2),number,result_ind); 00168 00169 // inv: result_ind < 28 00170 return gim_prime_list[result_ind]; 00171 } 00172 00173 00174 00176 00190 template<class T> 00191 class gim_hash_table 00192 { 00193 protected: 00194 typedef GIM_HASH_TABLE_NODE<T> _node_type; 00195 00197 //array< _node_type, SuperAllocator<_node_type> > m_nodes; 00198 gim_array< _node_type > m_nodes; 00199 //SuperBufferedArray< _node_type > m_nodes; 00200 bool m_sorted; 00201 00203 GUINT * m_hash_table; 00204 GUINT m_table_size; 00205 GUINT m_node_size; 00206 GUINT m_min_hash_table_size; 00207 00208 00209 00211 inline GUINT _find_cell(GUINT hashkey) 00212 { 00213 _node_type * nodesptr = m_nodes.pointer(); 00214 GUINT start_index = (hashkey%m_table_size)*m_node_size; 00215 GUINT end_index = start_index + m_node_size; 00216 00217 while(start_index<end_index) 00218 { 00219 GUINT value = m_hash_table[start_index]; 00220 if(value != GIM_INVALID_HASH) 00221 { 00222 if(nodesptr[value].m_key == hashkey) return start_index; 00223 } 00224 start_index++; 00225 } 00226 return GIM_INVALID_HASH; 00227 } 00228 00230 inline GUINT _find_avaliable_cell(GUINT hashkey) 00231 { 00232 _node_type * nodesptr = m_nodes.pointer(); 00233 GUINT avaliable_index = GIM_INVALID_HASH; 00234 GUINT start_index = (hashkey%m_table_size)*m_node_size; 00235 GUINT end_index = start_index + m_node_size; 00236 00237 while(start_index<end_index) 00238 { 00239 GUINT value = m_hash_table[start_index]; 00240 if(value == GIM_INVALID_HASH) 00241 { 00242 if(avaliable_index==GIM_INVALID_HASH) 00243 { 00244 avaliable_index = start_index; 00245 } 00246 } 00247 else if(nodesptr[value].m_key == hashkey) 00248 { 00249 return start_index; 00250 } 00251 start_index++; 00252 } 00253 return avaliable_index; 00254 } 00255 00256 00257 00259 00263 inline void _reserve_table_memory(GUINT newtablesize) 00264 { 00265 if(newtablesize==0) return; 00266 if(m_node_size==0) return; 00267 00268 //Get a Prime size 00269 00270 m_table_size = gim_next_prime(newtablesize); 00271 00272 GUINT datasize = m_table_size*m_node_size; 00273 //Alloc the data buffer 00274 m_hash_table = (GUINT *)gim_alloc(datasize*sizeof(GUINT)); 00275 } 00276 00277 inline void _invalidate_keys() 00278 { 00279 GUINT datasize = m_table_size*m_node_size; 00280 for(GUINT i=0;i<datasize;i++) 00281 { 00282 m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys 00283 } 00284 } 00285 00287 inline void _clear_table_memory() 00288 { 00289 if(m_hash_table==NULL) return; 00290 gim_free(m_hash_table); 00291 m_hash_table = NULL; 00292 m_table_size = 0; 00293 } 00294 00296 inline void _rehash() 00297 { 00298 _invalidate_keys(); 00299 00300 _node_type * nodesptr = m_nodes.pointer(); 00301 for(GUINT i=0;i<(GUINT)m_nodes.size();i++) 00302 { 00303 GUINT nodekey = nodesptr[i].m_key; 00304 if(nodekey != GIM_INVALID_HASH) 00305 { 00306 //Search for the avaliable cell in buffer 00307 GUINT index = _find_avaliable_cell(nodekey); 00308 00309 00310 if(m_hash_table[index]!=GIM_INVALID_HASH) 00311 {//The new index is alreade used... discard this new incomming object, repeated key 00312 btAssert(m_hash_table[index]==nodekey); 00313 nodesptr[i].m_key = GIM_INVALID_HASH; 00314 } 00315 else 00316 { 00317 //; 00318 //Assign the value for alloc 00319 m_hash_table[index] = i; 00320 } 00321 } 00322 } 00323 } 00324 00326 inline void _resize_table(GUINT newsize) 00327 { 00328 //Clear memory 00329 _clear_table_memory(); 00330 //Alloc the data 00331 _reserve_table_memory(newsize); 00332 //Invalidate keys and rehash 00333 _rehash(); 00334 } 00335 00337 inline void _destroy() 00338 { 00339 if(m_hash_table==NULL) return; 00340 _clear_table_memory(); 00341 } 00342 00344 inline GUINT _assign_hash_table_cell(GUINT hashkey) 00345 { 00346 GUINT cell_index = _find_avaliable_cell(hashkey); 00347 00348 if(cell_index==GIM_INVALID_HASH) 00349 { 00350 //rehashing 00351 _resize_table(m_table_size+1); 00352 GUINT cell_index = _find_avaliable_cell(hashkey); 00353 btAssert(cell_index!=GIM_INVALID_HASH); 00354 } 00355 return cell_index; 00356 } 00357 00359 inline bool _erase_by_index_hash_table(GUINT index) 00360 { 00361 if(index >= m_nodes.size()) return false; 00362 if(m_nodes[index].m_key != GIM_INVALID_HASH) 00363 { 00364 //Search for the avaliable cell in buffer 00365 GUINT cell_index = _find_cell(m_nodes[index].m_key); 00366 00367 btAssert(cell_index!=GIM_INVALID_HASH); 00368 btAssert(m_hash_table[cell_index]==index); 00369 00370 m_hash_table[cell_index] = GIM_INVALID_HASH; 00371 } 00372 00373 return this->_erase_unsorted(index); 00374 } 00375 00377 inline bool _erase_hash_table(GUINT hashkey) 00378 { 00379 if(hashkey == GIM_INVALID_HASH) return false; 00380 00381 //Search for the avaliable cell in buffer 00382 GUINT cell_index = _find_cell(hashkey); 00383 if(cell_index ==GIM_INVALID_HASH) return false; 00384 00385 GUINT index = m_hash_table[cell_index]; 00386 m_hash_table[cell_index] = GIM_INVALID_HASH; 00387 00388 return this->_erase_unsorted(index); 00389 } 00390 00391 00392 00394 00399 inline GUINT _insert_hash_table(GUINT hashkey, const T & value) 00400 { 00401 if(hashkey==GIM_INVALID_HASH) 00402 { 00403 //Insert anyway 00404 _insert_unsorted(hashkey,value); 00405 return GIM_INVALID_HASH; 00406 } 00407 00408 GUINT cell_index = _assign_hash_table_cell(hashkey); 00409 00410 GUINT value_key = m_hash_table[cell_index]; 00411 00412 if(value_key!= GIM_INVALID_HASH) return value_key;// Not overrited 00413 00414 m_hash_table[cell_index] = m_nodes.size(); 00415 00416 _insert_unsorted(hashkey,value); 00417 return GIM_INVALID_HASH; 00418 } 00419 00421 00426 inline GUINT _insert_hash_table_replace(GUINT hashkey, const T & value) 00427 { 00428 if(hashkey==GIM_INVALID_HASH) 00429 { 00430 //Insert anyway 00431 _insert_unsorted(hashkey,value); 00432 return GIM_INVALID_HASH; 00433 } 00434 00435 GUINT cell_index = _assign_hash_table_cell(hashkey); 00436 00437 GUINT value_key = m_hash_table[cell_index]; 00438 00439 if(value_key!= GIM_INVALID_HASH) 00440 {//replaces the existing 00441 m_nodes[value_key] = _node_type(hashkey,value); 00442 return value_key;// index of the replaced element 00443 } 00444 00445 m_hash_table[cell_index] = m_nodes.size(); 00446 00447 _insert_unsorted(hashkey,value); 00448 return GIM_INVALID_HASH; 00449 00450 } 00451 00452 00454 inline bool _erase_sorted(GUINT index) 00455 { 00456 if(index>=(GUINT)m_nodes.size()) return false; 00457 m_nodes.erase_sorted(index); 00458 if(m_nodes.size()<2) m_sorted = false; 00459 return true; 00460 } 00461 00463 inline bool _erase_unsorted(GUINT index) 00464 { 00465 if(index>=m_nodes.size()) return false; 00466 00467 GUINT lastindex = m_nodes.size()-1; 00468 if(index<lastindex && m_hash_table!=0) 00469 { 00470 GUINT hashkey = m_nodes[lastindex].m_key; 00471 if(hashkey!=GIM_INVALID_HASH) 00472 { 00473 //update the new position of the last element 00474 GUINT cell_index = _find_cell(hashkey); 00475 btAssert(cell_index!=GIM_INVALID_HASH); 00476 //new position of the last element which will be swaped 00477 m_hash_table[cell_index] = index; 00478 } 00479 } 00480 m_nodes.erase(index); 00481 m_sorted = false; 00482 return true; 00483 } 00484 00486 00489 inline void _insert_in_pos(GUINT hashkey, const T & value, GUINT pos) 00490 { 00491 m_nodes.insert(_node_type(hashkey,value),pos); 00492 this->check_for_switching_to_hashtable(); 00493 } 00494 00496 inline GUINT _insert_sorted(GUINT hashkey, const T & value) 00497 { 00498 if(hashkey==GIM_INVALID_HASH || size()==0) 00499 { 00500 m_nodes.push_back(_node_type(hashkey,value)); 00501 return GIM_INVALID_HASH; 00502 } 00503 //Insert at last position 00504 //Sort element 00505 00506 00507 GUINT result_ind=0; 00508 GUINT last_index = m_nodes.size()-1; 00509 _node_type * ptr = m_nodes.pointer(); 00510 00511 bool found = gim_binary_search_ex( 00512 ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); 00513 00514 00515 //Insert before found index 00516 if(found) 00517 { 00518 return result_ind; 00519 } 00520 else 00521 { 00522 _insert_in_pos(hashkey, value, result_ind); 00523 } 00524 return GIM_INVALID_HASH; 00525 } 00526 00527 inline GUINT _insert_sorted_replace(GUINT hashkey, const T & value) 00528 { 00529 if(hashkey==GIM_INVALID_HASH || size()==0) 00530 { 00531 m_nodes.push_back(_node_type(hashkey,value)); 00532 return GIM_INVALID_HASH; 00533 } 00534 //Insert at last position 00535 //Sort element 00536 GUINT result_ind; 00537 GUINT last_index = m_nodes.size()-1; 00538 _node_type * ptr = m_nodes.pointer(); 00539 00540 bool found = gim_binary_search_ex( 00541 ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); 00542 00543 //Insert before found index 00544 if(found) 00545 { 00546 m_nodes[result_ind] = _node_type(hashkey,value); 00547 } 00548 else 00549 { 00550 _insert_in_pos(hashkey, value, result_ind); 00551 } 00552 return result_ind; 00553 } 00554 00556 inline GUINT _insert_unsorted(GUINT hashkey, const T & value) 00557 { 00558 m_nodes.push_back(_node_type(hashkey,value)); 00559 m_sorted = false; 00560 return GIM_INVALID_HASH; 00561 } 00562 00563 00564 00565 public: 00566 00573 gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE, 00574 GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE, 00575 GUINT min_hash_table_size = GIM_INVALID_HASH) 00576 { 00577 m_hash_table = NULL; 00578 m_table_size = 0; 00579 m_sorted = false; 00580 m_node_size = node_size; 00581 m_min_hash_table_size = min_hash_table_size; 00582 00583 if(m_node_size!=0) 00584 { 00585 if(reserve_size!=0) 00586 { 00587 m_nodes.reserve(reserve_size); 00588 _reserve_table_memory(reserve_size); 00589 _invalidate_keys(); 00590 } 00591 else 00592 { 00593 m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE); 00594 _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE); 00595 _invalidate_keys(); 00596 } 00597 } 00598 else if(reserve_size!=0) 00599 { 00600 m_nodes.reserve(reserve_size); 00601 } 00602 00603 } 00604 00605 ~gim_hash_table() 00606 { 00607 _destroy(); 00608 } 00609 00610 inline bool is_hash_table() 00611 { 00612 if(m_hash_table) return true; 00613 return false; 00614 } 00615 00616 inline bool is_sorted() 00617 { 00618 if(size()<2) return true; 00619 return m_sorted; 00620 } 00621 00622 bool sort() 00623 { 00624 if(is_sorted()) return true; 00625 if(m_nodes.size()<2) return false; 00626 00627 00628 _node_type * ptr = m_nodes.pointer(); 00629 GUINT siz = m_nodes.size(); 00630 gim_sort_hash_node_array(ptr,siz); 00631 m_sorted=true; 00632 00633 00634 00635 if(m_hash_table) 00636 { 00637 _rehash(); 00638 } 00639 return true; 00640 } 00641 00642 bool switch_to_hashtable() 00643 { 00644 if(m_hash_table) return false; 00645 if(m_node_size==0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE; 00646 if(m_nodes.size()<GIM_DEFAULT_HASH_TABLE_SIZE) 00647 { 00648 _resize_table(GIM_DEFAULT_HASH_TABLE_SIZE); 00649 } 00650 else 00651 { 00652 _resize_table(m_nodes.size()+1); 00653 } 00654 00655 return true; 00656 } 00657 00658 bool switch_to_sorted_array() 00659 { 00660 if(m_hash_table==NULL) return true; 00661 _clear_table_memory(); 00662 return sort(); 00663 } 00664 00666 bool check_for_switching_to_hashtable() 00667 { 00668 if(this->m_hash_table) return true; 00669 00670 if(!(m_nodes.size()< m_min_hash_table_size)) 00671 { 00672 if(m_node_size == 0) 00673 { 00674 m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE; 00675 } 00676 00677 _resize_table(m_nodes.size()+1); 00678 return true; 00679 } 00680 return false; 00681 } 00682 00683 inline void set_sorted(bool value) 00684 { 00685 m_sorted = value; 00686 } 00687 00689 inline GUINT size() const 00690 { 00691 return m_nodes.size(); 00692 } 00693 00695 inline GUINT get_key(GUINT index) const 00696 { 00697 return m_nodes[index].m_key; 00698 } 00699 00701 00703 inline T * get_value_by_index(GUINT index) 00704 { 00705 return &m_nodes[index].m_data; 00706 } 00707 00708 inline const T& operator[](GUINT index) const 00709 { 00710 return m_nodes[index].m_data; 00711 } 00712 00713 inline T& operator[](GUINT index) 00714 { 00715 return m_nodes[index].m_data; 00716 } 00717 00719 00723 inline GUINT find(GUINT hashkey) 00724 { 00725 if(m_hash_table) 00726 { 00727 GUINT cell_index = _find_cell(hashkey); 00728 if(cell_index==GIM_INVALID_HASH) return GIM_INVALID_HASH; 00729 return m_hash_table[cell_index]; 00730 } 00731 GUINT last_index = m_nodes.size(); 00732 if(last_index<2) 00733 { 00734 if(last_index==0) return GIM_INVALID_HASH; 00735 if(m_nodes[0].m_key == hashkey) return 0; 00736 return GIM_INVALID_HASH; 00737 } 00738 else if(m_sorted) 00739 { 00740 //Binary search 00741 GUINT result_ind = 0; 00742 last_index--; 00743 _node_type * ptr = m_nodes.pointer(); 00744 00745 bool found = gim_binary_search_ex(ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); 00746 00747 00748 if(found) return result_ind; 00749 } 00750 return GIM_INVALID_HASH; 00751 } 00752 00754 00757 inline T * get_value(GUINT hashkey) 00758 { 00759 GUINT index = find(hashkey); 00760 if(index == GIM_INVALID_HASH) return NULL; 00761 return &m_nodes[index].m_data; 00762 } 00763 00764 00767 inline bool erase_by_index(GUINT index) 00768 { 00769 if(index > m_nodes.size()) return false; 00770 00771 if(m_hash_table == NULL) 00772 { 00773 if(is_sorted()) 00774 { 00775 return this->_erase_sorted(index); 00776 } 00777 else 00778 { 00779 return this->_erase_unsorted(index); 00780 } 00781 } 00782 else 00783 { 00784 return this->_erase_by_index_hash_table(index); 00785 } 00786 return false; 00787 } 00788 00789 00790 00791 inline bool erase_by_index_unsorted(GUINT index) 00792 { 00793 if(index > m_nodes.size()) return false; 00794 00795 if(m_hash_table == NULL) 00796 { 00797 return this->_erase_unsorted(index); 00798 } 00799 else 00800 { 00801 return this->_erase_by_index_hash_table(index); 00802 } 00803 return false; 00804 } 00805 00806 00807 00811 inline bool erase_by_key(GUINT hashkey) 00812 { 00813 if(size()==0) return false; 00814 00815 if(m_hash_table) 00816 { 00817 return this->_erase_hash_table(hashkey); 00818 } 00819 //Binary search 00820 00821 if(is_sorted()==false) return false; 00822 00823 GUINT result_ind = find(hashkey); 00824 if(result_ind!= GIM_INVALID_HASH) 00825 { 00826 return this->_erase_sorted(result_ind); 00827 } 00828 return false; 00829 } 00830 00831 void clear() 00832 { 00833 m_nodes.clear(); 00834 00835 if(m_hash_table==NULL) return; 00836 GUINT datasize = m_table_size*m_node_size; 00837 //Initialize the hashkeys. 00838 GUINT i; 00839 for(i=0;i<datasize;i++) 00840 { 00841 m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys 00842 } 00843 m_sorted = false; 00844 } 00845 00847 00851 inline GUINT insert(GUINT hashkey, const T & element) 00852 { 00853 if(m_hash_table) 00854 { 00855 return this->_insert_hash_table(hashkey,element); 00856 } 00857 if(this->is_sorted()) 00858 { 00859 return this->_insert_sorted(hashkey,element); 00860 } 00861 return this->_insert_unsorted(hashkey,element); 00862 } 00863 00865 00869 inline GUINT insert_override(GUINT hashkey, const T & element) 00870 { 00871 if(m_hash_table) 00872 { 00873 return this->_insert_hash_table_replace(hashkey,element); 00874 } 00875 if(this->is_sorted()) 00876 { 00877 return this->_insert_sorted_replace(hashkey,element); 00878 } 00879 this->_insert_unsorted(hashkey,element); 00880 return m_nodes.size(); 00881 } 00882 00883 00884 00886 00888 inline GUINT insert_unsorted(GUINT hashkey,const T & element) 00889 { 00890 if(m_hash_table) 00891 { 00892 return this->_insert_hash_table(hashkey,element); 00893 } 00894 return this->_insert_unsorted(hashkey,element); 00895 } 00896 00897 00898 }; 00899 00900 00901 00902 #endif // GIM_CONTAINERS_H_INCLUDED