cgma
DLIList.hpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines