cgma
|
00001 //- Class: DLIList 00002 //- 00003 //- Assumptions: All data are stored contiguously in the array with 00004 //- empty slots at the end of the array. 00005 //- 00006 //- Owner: Darryl Melander 00007 00008 #ifndef DLILIST_HPP 00009 #define DLILIST_HPP 00010 00011 #include "CubitDefines.h" 00012 #include <cstring> 00013 #include <vector> 00014 #include <set> 00015 #include <stdexcept> 00016 #include <algorithm> 00017 00018 #define DLI_COUNT_INCREMENT 8 00019 #define DLI_COUNT_FACTOR 1.5 00020 template<class X> class DLIListIterator; 00021 00022 00023 // the following empty template acts as a pure virtual declaration so that 00024 // new classes using DLIList will not be sorted by pointer 00025 template <class X> struct DLIListSorter 00026 { 00027 // bool operator()(const X &a, const X &b) { return a < b; } 00028 }; 00029 00030 // compare templates for intrinsic types 00031 00032 template <> struct DLIListSorter<int> 00033 { 00034 bool operator()(const int &a, const int &b) { return a < b; } 00035 }; 00036 00037 template <> struct DLIListSorter<double> 00038 { 00039 bool operator()(const double &a, const double &b) { return a < b; } 00040 }; 00041 00042 // compare template for CubitString. 00043 00044 //template <> struct DLIListSorter<CubitString> 00045 //{ 00046 // bool operator()(const CubitString &a, const CubitString &b) { return a < b; } 00047 //}; 00048 00050 00064 // The new Apple libc++ uses a specialization for std::vector<bool> that prevents 00065 // DLIList<bool> from re-using the std::vector<X>::const_reference typedef blindly. 00066 // vector_const_reference_type defined below provides a wrapper to consistently use 00067 // a plain bool type as DLIList<bool>::const_reference. 00068 template<typename T> 00069 struct vector_const_reference_type { 00070 typedef typename std::vector<T>::const_reference type; 00071 }; 00072 00073 template<> 00074 struct vector_const_reference_type<bool> { 00075 typedef bool type; 00076 }; 00077 00078 template<class X> class DLIList 00079 { 00080 public: 00081 friend class DLIListIterator<X>; 00082 00083 typedef typename std::vector<X>::reference reference; 00084 typedef typename vector_const_reference_type<X>::type const_reference; 00085 typedef typename std::vector<X>::pointer pointer; 00086 typedef typename std::vector<X>::const_pointer const_pointer; 00087 00088 typedef typename std::vector<X>::const_iterator const_iterator; 00089 typedef typename std::vector<X>::iterator iterator; 00090 00091 typedef typename std::vector<X>::value_type value_type; 00092 00094 00101 explicit DLIList (int size = 0); 00102 00104 00105 DLIList(const DLIList<X>& from); 00106 00108 00109 explicit DLIList(const std::vector<X>& from); 00110 00112 00116 ~DLIList(); 00117 00119 iterator begin(); 00120 00122 const_iterator begin() const; 00123 00125 iterator end(); 00126 00128 const_iterator end() const; 00129 00131 00132 void step(); 00133 00135 00139 void step(int n); 00140 00142 00143 void back(); 00144 00146 00149 void back(int n); 00150 00152 void reset(); 00154 void last(); 00155 00157 00160 void clean_out(); 00161 00163 00167 void shrink(int k); 00168 00170 CubitBoolean is_at_beginning() const; 00171 00173 CubitBoolean is_at_end() const; 00174 00176 void reverse(); 00177 00179 00181 DLIList<X>& operator=(const DLIList<X>& from); 00182 00184 00186 DLIList<X>& operator=(const std::vector<X>& from); 00187 00189 00194 DLIList<X>& operator=(const DLIListIterator<X>& from_iterator); 00195 00197 00201 DLIList<X>& operator+=(const DLIList<X>& from); 00202 00204 00208 DLIList<X>& operator+=(const std::vector<X>& from); 00209 00211 00216 DLIList<X>& operator-=(const DLIList<X>& from); 00217 00219 00225 int operator==(const DLIList<X>& from); 00226 00228 00234 int operator!=(const DLIList<X>& from); 00235 00237 00241 const_reference operator[](int index) const; 00242 reference operator[](int index); 00243 00245 reference last_item( void ); 00246 const_reference last_item( void ) const; 00247 00249 00265 void merge_unique(const DLIList<X>& merge_list, 00266 bool merge_list_unique = false); 00267 00269 00278 template<typename Y> inline void casting_merge_unique(const DLIList<Y>& merge_list, 00279 bool merge_list_unique = false) 00280 { 00281 // Save the current index of the merge_list 00282 int old_size = size(); 00283 int i, j, check_index; 00284 00285 X new_item; 00286 00287 // The resulting list will be at least as large as the larger of the two lists. 00288 // Reserve space so we don't have to reallocate so often. Note that if 00289 // this list is already bigger than merge_list, the reserve won't 00290 // make the list shorter. 00291 assert((int)merge_list.size() >= 0); // Assume that the merge list size does not exceed the maximum value for a signed integer 00292 reserve(merge_list.size()); 00293 00294 for ( i = 0; i < (int)merge_list.size(); i++) 00295 { 00296 // Get the item from the merge_list and insert it into "this" 00297 // list if it doesn't already exist there. 00298 new_item = static_cast<X>(merge_list[i]); 00299 check_index = merge_list_unique ? old_size : size(); 00300 00301 // Append the new item and then remove it if necessary. 00302 append(new_item); 00303 for ( j = 0; j < check_index; j++ ) 00304 { 00305 if ( listArray[j] == new_item ) 00306 { 00307 listArray.resize(listArray.size()-1); 00308 break; 00309 } 00310 } 00311 } 00312 } 00313 00315 00320 void intersect(const DLIList<X>& merge_list); 00322 00327 void intersect_unordered(const DLIList<X>& merge_list); 00328 00330 00333 CubitBoolean append_unique(const_reference new_item); 00334 00336 00340 void uniquify_unordered(); 00341 void uniquify_unordered_checked(); 00342 00344 00348 void uniquify_ordered(); 00349 00351 00361 X remove (); 00362 00364 00376 bool remove (const_reference val); 00377 00379 00388 void remove_all_with_value(const_reference val); 00389 00391 00401 CubitBoolean omit (const_reference val); 00402 00404 00406 const_reference get () const; 00407 reference get (); 00408 00410 00415 X next () const; 00416 00418 00425 X next (int n) const; 00426 00428 00433 X prev () const; 00434 00436 00443 X prev (int n) const; 00444 00446 00450 reference get_and_step (); 00451 00453 00458 reference get_and_back (); 00459 00461 00465 reference step_and_get (); 00466 00468 00470 CubitBoolean move_to(const_reference item); 00471 00473 00475 CubitBoolean is_in_list(const_reference item) const; 00476 00478 00480 X pop(); 00481 00483 00488 X push(X val); 00489 00491 00495 void insert (X val); 00496 00498 00502 void insert_first(X val); 00503 00505 00509 void append(const_reference new_item); 00510 00512 00515 X extract(); 00516 00518 00523 X change_to(X val); 00524 00526 00532 void sort(); 00533 00535 00543 typedef int (*SortFunction)(X& a, X& b); 00544 00546 00553 void sort(SortFunction f); 00554 00556 00560 void reserve(int min_size); 00561 00563 00564 int size() const 00565 { return (int)listArray.size(); } 00566 00568 00569 bool empty() const 00570 { return listArray.empty(); } 00571 00573 00574 int get_index() 00575 { return index; } 00576 00578 00584 int where_is_item(const_reference val) const; 00585 00587 int memory_use(); 00588 00590 00594 void copy_to(X *other_array); 00595 00597 00602 void copy_from(X *other_array, const int other_size); 00603 00605 00608 CubitBoolean move_to_nearby(const X val); 00609 00611 00616 int distance_to_nearby(const X val); 00617 00619 00627 CubitBoolean move_between(X val1, X val2); 00628 00630 00632 const std::vector<X>& as_vector() const; 00633 00634 00635 void swap(std::vector<X>& other); 00636 00637 private: 00638 void lengthen_list(int by_how_much = DLI_COUNT_INCREMENT, 00639 double by_what_factor = DLI_COUNT_FACTOR ); 00640 //- Makes the array bigger. Multiply current size 00641 //- "by_what_factor" and add 'by_how_much'. 00642 00643 int index; // Index of current item in {listArray} (so we should assume that the listArray size does not exceed the maximum value for a signed integer?) 00644 std::vector<X> listArray; 00645 }; 00646 00647 // *** inline function definitions ******************************************* 00648 template <class X> inline 00649 DLIList<X>& DLIList<X>::operator=(const DLIListIterator<X>& from_iter) 00650 { 00651 if ( from_iter.dlIList ) 00652 *this = *(from_iter.dlIList); 00653 else 00654 clean_out(); 00655 return *this; 00656 } 00657 00658 template <class X> inline 00659 typename DLIList<X>::const_reference DLIList<X>::operator[](int indexIn) const 00660 { 00661 assert((int)listArray.size() >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00662 if(indexIn < 0 || (size_t)indexIn >= listArray.size()) 00663 throw std::out_of_range("Index out of Bounds\n"); 00664 return listArray[indexIn]; 00665 } 00666 00667 template <class X> inline 00668 typename DLIList<X>::reference DLIList<X>::operator[](int indexIn) 00669 { 00670 assert((int)listArray.size() >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00671 if(indexIn < 0 || (size_t)indexIn >= listArray.size()) 00672 throw std::out_of_range("Index out of Bounds\n"); 00673 return listArray[indexIn]; 00674 } 00675 00676 template <class X> inline 00677 typename DLIList<X>::reference DLIList<X>::last_item(void) 00678 { 00679 assert( listArray.size() > 0 ); 00680 return listArray[listArray.size()-1]; 00681 } 00682 00683 template <class X> inline 00684 typename DLIList<X>::const_reference DLIList<X>::last_item(void) const 00685 { 00686 assert( listArray.size() > 0 ); 00687 return listArray[listArray.size()-1]; 00688 } 00689 00690 template <class X> inline void DLIList<X>::step() 00691 { 00692 if (!listArray.empty()) 00693 index++; 00694 assert((int)listArray.size() >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00695 if (index >= (int)listArray.size()) 00696 index = 0; 00697 } 00698 00699 template <class X> inline void DLIList<X>::step(int n) 00700 { 00701 const int itemCount = (int)listArray.size(); 00702 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00703 if (itemCount > 0) 00704 { 00705 index += n; 00706 if (index < 0) 00707 index = itemCount - (-index) % itemCount; 00708 if (index >= itemCount) 00709 index %= itemCount; 00710 } 00711 } 00712 00713 // Chop off the last (k) items in the list. 00714 template <class X> inline void DLIList<X>::shrink(int k) 00715 { 00716 if (k > 0) 00717 { 00718 const int itemCount = (int)listArray.size(); 00719 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00720 00721 if (itemCount > k) 00722 listArray.resize(itemCount - k); 00723 else 00724 listArray.clear(); 00725 00726 const int itemNewCount = (int)listArray.size(); 00727 if (index >= itemNewCount) 00728 { 00729 if (itemNewCount > 0) 00730 index = itemNewCount - 1; 00731 else 00732 index = 0; 00733 } 00734 } 00735 } 00736 00737 template <class X> inline void DLIList<X>::back() 00738 { 00739 const int itemCount = (int)listArray.size(); 00740 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00741 if (itemCount > 0) 00742 { 00743 index--; 00744 if (index < 0) 00745 index = itemCount - 1; 00746 } 00747 } 00748 00749 template <class X> inline void DLIList<X>::back(int n) 00750 { 00751 step(-n); 00752 } 00753 00754 template <class X> inline void DLIList<X>::reset() 00755 { 00756 index = 0; 00757 } 00758 00759 template <class X> inline void DLIList<X>::last() 00760 { 00761 const int itemCount = (int)listArray.size(); 00762 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00763 if (itemCount > 0) 00764 index = itemCount - 1; 00765 } 00766 00767 template <class X> inline CubitBoolean DLIList<X>::is_at_beginning() const 00768 { 00769 if (!index) 00770 return CUBIT_TRUE; 00771 else 00772 return CUBIT_FALSE; 00773 } 00774 00775 template <class X> inline CubitBoolean DLIList<X>::is_at_end() const 00776 { 00777 const int itemCount = (int)listArray.size(); 00778 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00779 if (itemCount == 0 || index == itemCount - 1) 00780 return CUBIT_TRUE; 00781 else 00782 return CUBIT_FALSE; 00783 } 00784 00785 template <class X> inline void DLIList<X>::clean_out() 00786 { 00787 listArray.clear(); 00788 index = 0; 00789 } 00790 00791 template <class X> inline CubitBoolean DLIList<X>::is_in_list(const_reference item) const 00792 { 00793 return where_is_item(item) >= 0 ? CUBIT_TRUE : CUBIT_FALSE; 00794 } 00795 00796 //- Add item to end of list, do not change current index value. 00797 //- This function used to reduce time required to do an insert 00798 //- followed by a move_to back to where we were. 00799 template <class X> inline void DLIList<X>::append(const_reference new_item) 00800 { 00801 // see if the list must be lengthened 00802 if (listArray.capacity() == listArray.size()) 00803 lengthen_list(); 00804 00805 listArray.push_back(new_item); 00806 } 00807 00808 template <class X> inline typename DLIList<X>::reference DLIList<X>::get() 00809 { 00810 if ( listArray.empty() ) 00811 { 00812 throw std::out_of_range("Attempted get of empty DLIList\n"); 00813 /*PRINT_WARNING("Attempted get of empty DLIList\n");*/ 00814 } 00815 00816 return listArray[index]; 00817 } 00818 00819 template <class X> inline typename DLIList<X>::const_reference DLIList<X>::get() const 00820 { 00821 if ( listArray.empty() ) 00822 { 00823 throw std::out_of_range("Attempted get of empty DLIList\n"); 00824 /*PRINT_WARNING("Attempted get of empty DLIList\n");*/ 00825 } 00826 return listArray[index]; 00827 } 00828 00829 template <class X> inline typename DLIList<X>::reference DLIList<X>::get_and_step() 00830 { 00831 if ( listArray.empty() ) 00832 { 00833 throw std::out_of_range("Attempted get_and_step from empty DLIList\n"); 00834 /*PRINT_WARNING("Attempted get_and_step from empty DLIList\n");*/ 00835 } 00836 reference temp = listArray[index++]; 00837 assert((int)listArray.size() >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00838 if (index == (int)listArray.size()) 00839 index = 0; 00840 return temp; 00841 } 00842 00843 template <class X> inline typename DLIList<X>::reference DLIList<X>::get_and_back () 00844 { 00845 if ( listArray.empty() ) 00846 { 00847 throw std::out_of_range("Attempted get_and_back from empty DLIList\n"); 00848 /*PRINT_WARNING("Attempted get_and_back from empty DLIList\n");*/ 00849 } 00850 reference temp = listArray[index--]; 00851 assert((int)listArray.size() >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00852 if (index < 0) 00853 index = (int)listArray.size() - 1; 00854 return temp; 00855 } 00856 00857 template <class X> inline X DLIList<X>::next() const 00858 { 00859 if (listArray.empty()) 00860 { 00861 throw std::out_of_range("Attempted next of empty DLIList\n"); 00862 /*PRINT_WARNING("Attempted next of empty DLIList\n");*/ 00863 } 00864 else { 00865 assert((int)listArray.size() >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00866 if (index == (int)listArray.size() - 1) 00867 return listArray[0]; 00868 else 00869 return listArray[index + 1]; 00870 } 00871 } 00872 00873 template <class X> inline X DLIList<X>::next(int n) const 00874 { 00875 if ( listArray.empty() ) 00876 { 00877 throw std::out_of_range("Attempted next of empty DLIList\n"); 00878 /*PRINT_WARNING("Attempted next of empty DLIList\n");*/ 00879 } 00880 else 00881 { 00882 // return the proper index 00883 // beware of negative n leading to negative new_index 00884 int new_index = index+n; 00885 assert((int)listArray.size() >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00886 while (new_index < 0) 00887 new_index += listArray.size(); 00888 if ((size_t)new_index >= listArray.size()) 00889 new_index %= listArray.size(); 00890 00891 return listArray[new_index]; 00892 } 00893 } 00894 00895 template <class X> inline X DLIList<X>::prev() const 00896 { 00897 return this->next(-1); 00898 } 00899 00900 template <class X> inline X DLIList<X>::prev(int n) const 00901 { 00902 return this->next(-n); 00903 } 00904 00905 //- put new item in list at index 0 and make it current 00906 template <class X> inline void DLIList<X>::insert_first(X new_item) 00907 { 00908 // set index to -1 ... index will be set to 0 in insert 00909 index = -1; 00910 insert(new_item); 00911 } 00912 00913 template <class X> inline CubitBoolean DLIList<X>::move_to (const_reference item) 00914 { 00915 int item_index = where_is_item(item); 00916 CubitBoolean rv = CUBIT_FALSE; 00917 if (item_index >= 0) 00918 { 00919 index = item_index; 00920 rv = CUBIT_TRUE; 00921 } 00922 return rv; 00923 } 00924 00925 template <class X> inline X DLIList<X>::change_to (X new_value) 00926 { 00927 if ( listArray.empty() ) 00928 { 00929 throw std::out_of_range("DLIList: Attempted update of empty list\n"); 00930 //PRINT_WARNING("DLIList: Attempted update of empty list\n"); 00931 } 00932 00933 X temp = listArray[index]; 00934 listArray[index] = new_value; 00935 return temp; 00936 } 00937 00938 // Removes every instance of 'val' in list. 00939 // Set to beginning of list after this call. 00940 template <class X> inline void DLIList<X>::remove_all_with_value(const_reference val) 00941 { 00942 size_t j = 0; 00943 size_t i = 0; 00944 const size_t itemCount = listArray.size(); 00945 00946 for ( ; i < itemCount; i++) 00947 if (listArray[i] != val && j++ != i) 00948 listArray[j-1] = listArray[i]; 00949 00950 listArray.resize(j); 00951 index = 0; 00952 } 00953 00954 // Searches for item and removes the next instance from the list. 00955 // If the item was found and removed it is returned, else 0 is returned. 00956 template <class X> inline bool DLIList<X>::remove (const_reference item) 00957 { 00958 if (move_to(item)) 00959 { 00960 remove(); 00961 return true; 00962 } 00963 return false; 00964 } 00965 00966 template <class X> inline int DLIList<X>::where_is_item (const_reference item) const 00967 { 00968 if (listArray.empty()) 00969 return -1; 00970 00971 const int itemCount = (int)listArray.size(); 00972 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 00973 00974 // loop through list searching for item ... 00975 // if found return index 00976 00977 // Search from current index to end of array 00978 int i; 00979 for (i=index; i < itemCount; i++) 00980 if (listArray[i] == item) 00981 return i; 00982 00983 // Now search from beginning of array to index... 00984 for (i = 0; i < index && i < itemCount; i++) 00985 if (listArray[i] == item) 00986 return i; 00987 00988 // item is not in array, return -1 00989 return -1; 00990 } 00991 //- Append this new_item to the list if it doesn't already exist in it. 00992 //- Make sure the index is unchanged. 00993 template <class X> inline CubitBoolean DLIList<X>::append_unique(const_reference new_item) 00994 { 00995 // Append new_item, if it isn't already there. 00996 if( where_is_item(new_item) < 0 ) 00997 { 00998 append (new_item); 00999 return CUBIT_TRUE; 01000 } 01001 return CUBIT_FALSE; 01002 } 01003 01004 template <class X> inline X DLIList<X>::push(X value) 01005 { 01006 //- swapped last and append; current position is set new end 01007 append(value); 01008 last(); 01009 return value; 01010 } 01011 01012 template <class X> inline X DLIList<X>::pop() 01013 { 01014 last(); 01015 return remove(); 01016 } 01017 01018 //- Constructor: Create a list with initial size 0. The list 01019 //- will be grown by {increment} each time it is filled. Memory for the 01020 //- list is not allocated until the first element is inserted using 01021 //- {insertLink}. 01022 template <class X> inline DLIList<X>::DLIList (int sizeIn) 01023 { 01024 index = 0; 01025 listArray.reserve(sizeIn); 01026 } 01027 01028 //- Copy Constructor 01029 template <class X> inline DLIList<X>::DLIList(const DLIList<X>& from) 01030 { 01031 if (&from != this) 01032 { 01033 index = from.index; 01034 listArray = from.listArray; 01035 } 01036 } 01037 01038 //- Copy constructor for std::vector 01039 template <class X> inline DLIList<X>::DLIList(const std::vector<X>& from) 01040 { 01041 // Setup the variables 01042 index = 0; 01043 listArray = from; 01044 } 01045 01046 // Destructor 01047 template <class X> inline DLIList<X>::~DLIList() 01048 { 01049 } 01050 01051 template <class X> inline void DLIList<X>::reserve(int min_size) 01052 { 01053 listArray.reserve(min_size); 01054 } 01055 01056 template <class X> inline void DLIList<X>::lengthen_list(int by_how_much, 01057 double by_what_factor) 01058 { 01059 // Make a new array 01060 int new_size = (int) ((double)listArray.capacity() * by_what_factor) + by_how_much; 01061 assert(new_size > 0); 01062 reserve(new_size); 01063 } 01064 01065 //- put new item in list after current item and make it current 01066 template <class X> inline void DLIList<X>::insert(X new_item) 01067 { 01068 // see if the list must be lengthened 01069 if ( listArray.size() == listArray.capacity()) 01070 { 01071 lengthen_list(); 01072 } 01073 01074 // set new index 01075 if ( !listArray.empty() ) 01076 { 01077 index++; 01078 } 01079 else 01080 { 01081 index = 0; 01082 } 01083 01084 listArray.insert(listArray.begin()+index, new_item); 01085 } 01086 01087 //- merge the input list, merge_list, with the current list, making 01088 //- sure not to add duplicate items into the current list 01089 template <class X> inline 01090 void DLIList<X>::merge_unique ( const DLIList<X>& merge_list, 01091 bool merge_list_unique ) 01092 { 01093 this->casting_merge_unique(merge_list, merge_list_unique); 01094 } 01095 01096 template <class X> inline void DLIList<X>::intersect_unordered( 01097 const DLIList<X>& merge_list ) 01098 { 01099 if ( &merge_list == this ) 01100 return; 01101 01102 intersect (merge_list); 01103 return; 01104 01105 DLIList <X> intersect_list(merge_list); // copy input list so can sort 01106 sort(); 01107 intersect_list.sort(); 01108 01109 typename std::vector<X>::iterator iter1 = listArray.begin(); // iterator for this array 01110 typename std::vector<X>::iterator end1 = listArray.end(); // end of this array 01111 typename std::vector<X>::iterator iter2 = intersect_list.listArray.begin(); // iterstor for other array 01112 typename std::vector<X>::iterator end2 = intersect_list.listArray.end();// end of other array 01113 typename std::vector<X>::iterator insertIt; // location of last insert 01114 bool first = true; 01115 01116 for ( ; iter1 < end1; ++iter1 ) 01117 { 01118 while (iter2 < end2 && *iter2 < *iter1) 01119 ++iter2; 01120 01121 if (iter2 == end2) 01122 break; 01123 01124 // items are the same and ... 01125 if (*iter2 == *iter1) 01126 { 01127 // is the first item or ... 01128 if(first) 01129 { 01130 first = false; 01131 insertIt = listArray.begin(); 01132 *insertIt = *iter1; 01133 } 01134 // is not the same as the previous item 01135 else if(*iter1 != *insertIt) 01136 { 01137 *++insertIt = *iter1; 01138 } 01139 } 01140 } 01141 01142 if(first) 01143 { 01144 // no intersections 01145 listArray.clear(); 01146 } 01147 else 01148 { 01149 listArray.resize(insertIt - listArray.begin() + 1); 01150 } 01151 reset(); 01152 } 01153 01154 template <class X> inline void DLIList<X>::intersect ( const DLIList<X>& merge_list ) 01155 { 01156 if ( &merge_list == this ) 01157 return; 01158 01159 const int itemCount = (int)listArray.size(); 01160 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 01161 std::vector<X> tmp; 01162 01163 for ( int i=0; i<itemCount; i++ ) 01164 { 01165 if (merge_list.is_in_list(listArray[i])) 01166 { 01167 tmp.push_back(listArray[i]); 01168 } 01169 } 01170 01171 this->listArray.swap(tmp); 01172 index = 0; 01173 } 01174 01175 //template <class X> inline void DLIList<X>::intersect ( void* merge_list ) 01176 //{ 01177 // intersect( *(DLIList<X>*)merge_list ); 01178 //} 01179 01180 01181 //- remove the item at the current location and return a pointer to it. 01182 //- The next node becomes the current node 01183 //- Returns 0 if there are no items in list 01184 template <class X> inline X DLIList<X>::remove () 01185 { 01186 if ( listArray.empty() ) 01187 { 01188 throw std::out_of_range("Attempted link removal from empty DLIList\n"); 01189 /*PRINT_WARNING("Attempted link removal from empty DLIList\n");*/ 01190 } 01191 01192 // save the current value 01193 X temp = listArray[index]; 01194 01195 listArray.erase(listArray.begin() + index); 01196 assert((int)listArray.size() >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 01197 if ( index == (int)listArray.size() ) 01198 { 01199 index = 0; 01200 } 01201 01202 return temp; 01203 } 01204 01205 01206 //- remove the item at the current location and return a pointer to it. 01207 //- used for efficiency in cases where preservation of list order is not 01208 //- important. moves last list item (itemCount - 1) to current index and 01209 //- decrements itemCount. eliminates the need to perform the list bubble 01210 //- down (i.e. cut_link) but sacrifices list order in the process. this 01211 //- function should not be used when up-stream order from the removed node is 01212 //- important. when processing a list using this function the user should 01213 //- reset the list to the head (index = 0) before beginning to ensure all 01214 //- list nodes are processed properly. 01215 //- Returns 0 if there are no items in list 01216 template <class X> inline X DLIList<X>::extract () 01217 { 01218 if ( listArray.empty() ) 01219 { 01220 throw std::out_of_range("Attempted link removal from empty DLIList\n"); 01221 /*PRINT_WARNING("Attempted link removal from empty DLIList\n");*/ 01222 } 01223 01224 // save the current value 01225 X temp = listArray[index]; 01226 01227 // assign last node to the current index 01228 listArray[index] = listArray[listArray.size() - 1]; 01229 01230 // decrement 01231 listArray.resize(listArray.size() - 1); 01232 assert((int)listArray.size() >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 01233 if ( index == (int)listArray.size() && index > 0) 01234 // The choices here are index at beginning or end. 01235 // End seems to work better when 'extract' is being used 01236 // with calls to 'move_to_item'. 01237 index--; 01238 01239 return temp; 01240 } 01241 01242 //+//Added so list removals don't disturb current position. PRK 05-23-94 01243 //+//Corrected for omitting the last item in the list. PRK 09-16-94 01244 //+//Corrected for omitting before the current position. PRK 10-07-94 01245 //- Finds instance of item by matching value and delets first instance 01246 //- of it from the list. The current position of the list is not changed. 01247 //- Returns CUBIT_TRUE if the item was found and deleted, CUBIT_FALSE if not. 01248 template <class X> inline CubitBoolean DLIList<X>::omit(const_reference old_val) 01249 { 01250 int scan_index; 01251 int squeeze_index = 0; 01252 CubitBoolean found = CUBIT_FALSE; 01253 const int itemCount = (int)listArray.size(); 01254 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 01255 for(scan_index = 0; scan_index < itemCount; ++scan_index) 01256 { 01257 if(listArray[scan_index] == old_val) 01258 { 01259 found = CUBIT_TRUE; 01260 if(index == scan_index) 01261 index = squeeze_index - 1; 01262 } 01263 else 01264 { 01265 if(scan_index != squeeze_index) 01266 { 01267 listArray[squeeze_index] = listArray[scan_index]; 01268 if(index == scan_index) index = squeeze_index; 01269 } 01270 ++squeeze_index; 01271 } 01272 } 01273 01274 if(found) 01275 { 01276 listArray.resize(squeeze_index); 01277 //+// If the first item was deleted and index pointed to it, make an 01278 //+// adjustment here. If itemCount is zero, don't assign -1 again. 01279 if(index < 0) 01280 index = listArray.empty() ? 0 : listArray.size()-1; 01281 } 01282 01283 return found; 01284 } 01285 01286 template <class X> inline typename DLIList<X>::reference DLIList<X>::step_and_get () 01287 { 01288 if ( listArray.empty() ) 01289 { 01290 throw std::out_of_range("Attempted step_and_get from empty DLIList\n"); 01291 /*PRINT_WARNING("Attempted step_and_get from empty DLIList\n");*/ 01292 } 01293 assert((int)listArray.size() >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 01294 if (++index == (int)listArray.size()) 01295 index = 0; 01296 return listArray[index]; 01297 } 01298 01299 template <class X> inline DLIList<X>& DLIList<X>:: 01300 operator=(const DLIList<X>& from) 01301 { 01302 if (this != &from) 01303 { 01304 index = from.index; 01305 listArray = from.listArray; 01306 } 01307 return *this; 01308 } 01309 01310 template <class X> inline DLIList<X>& DLIList<X>:: 01311 operator=(const std::vector<X>& from) 01312 { 01313 index = 0; 01314 listArray = from; 01315 return *this; 01316 } 01317 01318 template <class X> inline DLIList<X>& DLIList<X>:: 01319 operator+=(const DLIList<X>& from) 01320 { 01321 listArray.insert(listArray.end(), from.listArray.begin(), from.listArray.end()); 01322 return *this; 01323 } 01324 01325 template <class X> inline DLIList<X>& DLIList<X>:: 01326 operator+=(const std::vector<X>& from) 01327 { 01328 listArray.insert(listArray.end(), from.begin(), from.end()); 01329 return *this; 01330 } 01331 01332 template <class X> inline DLIList<X>& DLIList<X>:: 01333 operator-=(const DLIList<X>& from) 01334 { 01335 // step through items in from list, removing them from this list. 01336 for (int i = from.listArray.size(); i--; ) 01337 { 01338 // quit early if this list is empty. 01339 if (listArray.empty()) 01340 break; 01341 remove_all_with_value(from.listArray[i]); 01342 } 01343 return *this; 01344 } 01345 01346 template <class X> inline int DLIList<X>::operator==(const DLIList<X> &from) 01347 { 01348 if(listArray.size() != from.listArray.size()) 01349 return CUBIT_FALSE; 01350 DLIList<X> temp_list = from; 01351 for( size_t i = 0; i < listArray.size(); i++) 01352 if(temp_list.move_to(listArray[i])) 01353 temp_list.remove(); 01354 return temp_list.listArray.size() == 0; 01355 } 01356 template <class X> inline int DLIList<X>::operator!=(const DLIList<X> &from) 01357 { 01358 return !( *this == from ); 01359 } 01360 01361 // Sorts list from low to high value, according to the > operator 01362 // of the list type. 01363 // List is sorted using a standard Heap Sort algorithm ("Algorithms in C++", 01364 // Robert Sedgewick). 01365 template <class X> inline void DLIList<X>::sort(typename DLIList<X>::SortFunction f) 01366 { 01367 // Only sort it if there is more than one 01368 // item in the list 01369 const int itemCount = (int)listArray.size(); 01370 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 01371 if (itemCount > 1) 01372 { 01373 01374 //std::sort(listArray.begin(),listArray.end(),f); 01375 //return; 01376 01377 int mid = (itemCount >> 1) + 1; 01378 int ir = itemCount; 01379 X temp_element; 01380 01381 // You loop until ir is 1 (ir = iterations remaining) 01382 while(CUBIT_TRUE) 01383 { 01384 if (mid > 1) 01385 { 01386 mid--; 01387 temp_element = listArray[mid - 1]; 01388 } 01389 else 01390 { 01391 ir--; 01392 temp_element = listArray[ir]; 01393 listArray[ir] = listArray[0]; 01394 if (ir == 1) 01395 { 01396 listArray[0] = temp_element; 01397 return; 01398 } 01399 } 01400 01401 int i = mid; 01402 int j = mid + mid; 01403 01404 while (j <= ir) 01405 { 01406 if (j < ir) 01407 { 01408 if (f(listArray[j], listArray[j - 1]) >= 0) 01409 j++; 01410 } 01411 if (f(listArray[j - 1], temp_element) >= 0) 01412 { 01413 listArray[i - 1] = listArray[j - 1]; 01414 i = j; 01415 j += j; 01416 } 01417 else 01418 { 01419 j = ir + 1; 01420 } 01421 } 01422 listArray[i - 1] = temp_element; 01423 } 01424 } 01425 } 01426 01427 template <class X> inline void DLIList<X>::sort() 01428 { 01429 const int itemCount = (int)listArray.size(); 01430 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 01431 // Only sort it if there is more than one 01432 // item in the list 01433 if (itemCount > 1) 01434 { 01435 //std::sort(listArray.begin(),listArray.end(),DLIListSorter<X>()); 01436 //return; 01437 01438 int mid = (itemCount >> 1) + 1; 01439 int ir = itemCount; 01440 X temp_element; 01441 01442 // You loop until ir is 1 (ir = iterations remaining) 01443 while(CUBIT_TRUE) 01444 { 01445 if (mid > 1) 01446 { 01447 mid--; 01448 temp_element = listArray[mid - 1]; 01449 } 01450 else 01451 { 01452 ir--; 01453 temp_element = listArray[ir]; 01454 listArray[ir] = listArray[0]; 01455 if (ir == 1) 01456 { 01457 listArray[0] = temp_element; 01458 return; 01459 } 01460 } 01461 01462 int i = mid; 01463 int j = mid + mid; 01464 01465 while (j <= ir) 01466 { 01467 if (j < ir) 01468 { 01469 if (listArray[j] >= listArray[j - 1]) 01470 j++; 01471 } 01472 if (listArray[j - 1] >= temp_element) 01473 { 01474 listArray[i - 1] = listArray[j - 1]; 01475 i = j; 01476 j += j; 01477 } 01478 else 01479 { 01480 j = ir + 1; 01481 } 01482 } 01483 listArray[i - 1] = temp_element; 01484 } 01485 } 01486 01487 } 01488 01489 template <class X> inline void DLIList<X>::reverse() 01490 { 01491 int front = 0; 01492 assert((int)listArray.size() >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 01493 int tail = (int)listArray.size() - 1; 01494 X temp; 01495 01496 while (front < tail) 01497 { 01498 temp = listArray[front]; 01499 listArray[front] = listArray[tail]; 01500 listArray[tail] = temp; 01501 tail--; 01502 front++; 01503 } 01504 } 01505 01506 template <class X> inline int DLIList<X>::memory_use() 01507 { 01508 // report amount of memory allocated 01509 01510 int sizeIn = listArray.capacity() * sizeof(X); 01511 01512 // if (verbose_boolean) 01513 // { 01514 // PRINT_INFO(" DLIList: %d bytes\n",sizeIn); 01515 // } 01516 01517 return sizeIn; 01518 } 01519 01520 template <class X> inline void DLIList<X>::copy_to(X *other_array) 01521 //- copy this list's listArray into other_array 01522 { 01523 if(other_array == 0) 01524 throw std::invalid_argument("Array is NULL"); 01525 01526 if (listArray.size() > 0) 01527 { 01528 const int itemCount = (int)listArray.size(); 01529 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 01530 for (int i = 0; i < itemCount; i++) 01531 other_array[i] = listArray[i]; 01532 } 01533 } 01534 01535 template <class X> inline void DLIList<X>::copy_from(X *other_array, const int other_size) 01536 //- copy other_array into listArray 01537 { 01538 if(other_array == 0) 01539 throw std::invalid_argument("Array is NULL"); 01540 01541 listArray.clear(); 01542 listArray.insert(listArray.end(), other_array, other_array+other_size); 01543 index = 0; 01544 } 01545 01546 template <class X> inline CubitBoolean DLIList<X>::move_to_nearby(const X item) 01547 { 01548 // if (nullItem && (X)nullItem == item) 01549 // return CUBIT_FALSE; 01550 // else 01551 if (listArray.empty()) 01552 return CUBIT_FALSE; 01553 else 01554 { 01555 const int itemCount = (int)listArray.size(); 01556 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 01557 typename std::vector<X>::iterator ptr_up = listArray.begin() + index; 01558 if (*ptr_up == item) 01559 return CUBIT_TRUE; 01560 01561 int i_up, i_down; 01562 i_up = i_down = index; 01563 typename std::vector<X>::iterator ptr_down = ptr_up; 01564 while (1) 01565 { 01566 // check forward in the list increment 01567 if ( ++i_up < itemCount ) 01568 ptr_up++; 01569 else 01570 { 01571 i_up = 0; 01572 ptr_up = listArray.begin(); 01573 } 01574 // check 01575 if ( *ptr_up == item ) 01576 { 01577 index = i_up; 01578 return CUBIT_TRUE; 01579 } 01580 if ( i_up == i_down ) 01581 { 01582 return CUBIT_FALSE; 01583 } 01584 01585 // check backward in the list 01586 // increment 01587 if ( --i_down >= 0 ) 01588 ptr_down--; 01589 else 01590 { 01591 i_down = itemCount-1; 01592 ptr_down = listArray.begin()+ i_down; 01593 } 01594 // check 01595 if ( *ptr_down == item ) 01596 { 01597 index = i_down; 01598 return CUBIT_TRUE; 01599 } 01600 if ( i_up == i_down ) 01601 { 01602 return CUBIT_FALSE; 01603 } 01604 01605 } 01606 } 01607 } 01608 01609 template <class X> inline int DLIList<X>::distance_to_nearby(const X body) 01610 { 01611 // if (nullItem && (X)nullItem == body) 01612 // return CUBIT_FALSE; 01613 // else 01614 { 01615 int old_index = index; 01616 move_to_nearby( body ); 01617 int distance = abs(index - old_index); 01618 if (distance > listArray.size() / 2) 01619 distance = listArray.size() - distance; 01620 index = old_index; 01621 return distance; 01622 } 01623 } 01624 01625 template <class X> inline CubitBoolean DLIList<X>::move_between(X item1, X item2) 01626 { 01627 { 01628 if ( listArray.empty() ) 01629 return CUBIT_FALSE; 01630 01631 const int itemCount = (int)listArray.size(); 01632 assert(itemCount >= 0); // Assume that the listArray size does not exceed the maximum value for a signed integer 01633 01634 for ( int i = 0; i < itemCount; i++ ) 01635 { 01636 if ( listArray[i] == item1 ) 01637 { 01638 // dance around looking for item2 01639 if ( i+1 < itemCount ) { 01640 if ( listArray[i+1] == item2 ) { 01641 index = i+1; 01642 return CUBIT_TRUE; 01643 } 01644 } 01645 if ( i > 0 ) { 01646 if ( listArray[i-1] == item2 ) { 01647 index = i; 01648 return CUBIT_TRUE; 01649 } 01650 } 01651 if ( ( i+1 == itemCount && listArray[0] == item2 ) 01652 || ( i == 0 && listArray[itemCount-1] == item2 ) ) 01653 { 01654 index = 0; 01655 return CUBIT_TRUE; 01656 } 01657 } 01658 } 01659 return CUBIT_FALSE; 01660 } 01661 } 01662 01663 // Removes every instance of 'val' in list. 01664 // Set to beginning of list after this call. 01665 template <class X> inline void DLIList<X>::uniquify_unordered() 01666 { 01667 const size_t itemCount = listArray.size(); 01668 if ( itemCount < 2 ) 01669 return; 01670 01671 sort(); 01672 01673 listArray.erase(std::unique(listArray.begin(), listArray.end()), listArray.end()); 01674 01675 index = 0; 01676 } 01677 // Removes every instance of 'val' in list. 01678 // Set to beginning of list after this call. 01679 template <class X> inline void DLIList<X>::uniquify_unordered_checked() 01680 { 01681 const size_t itemCount = listArray.size(); 01682 if ( itemCount < 2 ) 01683 return; 01684 01685 sort(); 01686 01687 size_t j = 1; 01688 size_t i = 0; 01689 01690 while (j < itemCount) 01691 { 01692 if (listArray[i] != listArray[j]) 01693 listArray[++i] = listArray[j++]; 01694 else 01695 j++; 01696 } 01697 01698 listArray.resize(i + 1); 01699 index = 0; 01700 } 01701 01702 template <class X> inline void DLIList<X>::uniquify_ordered() 01703 { 01704 std::set<X> encountered; 01705 typename std::vector<X>::iterator read_iter, write_iter, end_iter = listArray.end(); 01706 01707 // To avoid copying the array onto itself in the case 01708 // where the list contains no duplicates, loop twice. 01709 01710 // Find first duplicate entry. 01711 for ( read_iter = listArray.begin(); read_iter != end_iter; ++read_iter ) 01712 if ( ! encountered.insert(*read_iter).second ) 01713 break; 01714 01715 // Now compact array, removing duplicates. If there 01716 // are no duplicates, this loop will not run (read_iter == end_iter). 01717 for ( write_iter = read_iter; read_iter != end_iter; ++read_iter ) 01718 if ( encountered.insert(*read_iter).second ) 01719 *(write_iter++) = *read_iter; 01720 01721 listArray.resize(write_iter - listArray.begin()); 01722 index = 0; 01723 } 01724 01725 template <class X> inline const std::vector<X>& DLIList<X>::as_vector() const 01726 { 01727 return listArray; 01728 } 01729 01730 template <class X> class DLIListIterator 01731 { 01732 friend class DLIList<X>; 01733 public: 01734 // constructor 01735 DLIListIterator() : 01736 mIndex(0), 01737 dlIList(NULL) 01738 {} 01739 01740 // destructor 01741 virtual ~DLIListIterator() 01742 {} 01743 01744 void watch( const DLIList <X> *dl_i_list ) 01745 { 01746 dlIList = dl_i_list; 01747 mIndex = dlIList->index; 01748 } 01749 01750 void reset() 01751 { mIndex = 0; } 01752 01753 void step( int n = 1 ) 01754 { 01755 if (!size()) 01756 mIndex = 0; 01757 else 01758 { 01759 mIndex += n; 01760 while (mIndex < 0) 01761 mIndex += dlIList->size(); 01762 mIndex %= dlIList->size(); 01763 } 01764 } 01765 01766 int size() const 01767 { return dlIList ? dlIList->size() : 0; } 01768 01769 X get() const 01770 { return next(0); } 01771 X next( int n = 1 ) const; 01772 X get_and_step( int n = 1 ) 01773 { 01774 X temp = get(); 01775 step( n ); 01776 return temp; 01777 } 01778 01779 //- Moves to the next instance of this value, wrapping if necessary 01780 CubitBoolean move_to(X item) 01781 { 01782 mIndex = where_is_item( item ); 01783 return mIndex >= 0 ? CUBIT_TRUE : CUBIT_FALSE; 01784 } 01785 01786 //- Return True if item is in the list, false otherwise. 01787 CubitBoolean is_in_list(X item) const 01788 { return where_is_item(item) >= 0 ? CUBIT_TRUE : CUBIT_FALSE; } 01789 01790 // Returns CUBIT_TRUE if we're pointing at the last item in the list. 01791 CubitBoolean is_at_end() const 01792 { 01793 if (size() == 0 || mIndex == size() - 1) 01794 return CUBIT_TRUE; 01795 return CUBIT_FALSE; 01796 } 01797 01798 //- returns CUBIT_TRUE if we're pointing at the first item in the list. 01799 CubitBoolean is_at_beginning() const 01800 { 01801 if (!mIndex || mIndex == size()) 01802 return CUBIT_TRUE; 01803 return CUBIT_FALSE; 01804 } 01805 01806 protected: 01807 // utility functions 01808 int where_is_item( X item ) const 01809 { return dlIList ? dlIList->where_is_item( item ) : -1; } 01810 01811 // data 01812 int mIndex; 01813 const DLIList<X> *dlIList; 01814 }; 01815 01816 template <class X> 01817 inline X DLIListIterator<X>::next( int n ) const 01818 { 01819 int size_loc = size(); 01820 if ( size_loc == 0 ) 01821 return NULL; 01822 int index_loc = mIndex + n; 01823 while ( index_loc < 0 ) 01824 index_loc += size_loc; 01825 while ( index_loc >= size_loc ) 01826 index_loc -= size_loc; 01827 01828 // if dlIList == NULL, then size == 0 and returned already 01829 return dlIList->listArray[index_loc]; 01830 } 01831 01832 template <class X> 01833 inline typename DLIList<X>::iterator DLIList<X>::begin() 01834 { 01835 return this->listArray.begin(); 01836 } 01837 01838 template <class X> 01839 inline typename DLIList<X>::const_iterator DLIList<X>::begin() const 01840 { 01841 return this->listArray.begin(); 01842 } 01843 01844 template <class X> 01845 inline typename DLIList<X>::iterator DLIList<X>::end() 01846 { 01847 return this->listArray.end(); 01848 } 01849 01850 template <class X> 01851 inline typename DLIList<X>::const_iterator DLIList<X>::end() const 01852 { 01853 return this->listArray.end(); 01854 } 01855 01856 template <class X> inline void DLIList<X>::swap(std::vector<X>& other) 01857 { 01858 this->listArray.swap(other); 01859 } 01860 01861 01862 #endif //- DLILIST_HPP 01863