Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
cmplr_segmented_array.h
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 /* -*-Mode: c++;-*- (Tell emacs to use c++ mode) */
00037 
00038 #ifndef cmplr_segmented_array_INCLUDED
00039 #define cmplr_segmented_array_INCLUDED
00040 
00041 #ifndef __SGI_STL_ALGO_H
00042 
00043 #if defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00044 #undef short                            // get around bogus type defs.
00045 #undef int
00046 #undef long
00047 #endif // defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00048 
00049 #include <algorithm>
00050 #include <vector>
00051 
00052 using std::find;
00053 using std::transform;
00054 using std::sort;
00055 using std::stable_sort;
00056 using std::rotate;
00057 using std::reverse;
00058 using std::set_union;
00059 using std::set_intersection;
00060 using std::set_difference;
00061 using std::min;
00062 using std::pair;
00063 using std::vector;
00064 
00065 #endif // __SGI_STL_ALGO_H
00066 
00067 #ifndef __SGI_STL_VECTOR_H
00068 
00069 #if defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00070 #undef short                            // get around bogus type defs.
00071 #undef int
00072 #undef long
00073 #endif // defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00074 
00075 //# include <vector>
00076 //using std::vector;
00077 
00078 #endif // __SGI_STL_VECTOR_H
00079 
00080 #ifndef __SGI_STL_SLIST_H
00081 
00082 #if defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00083 #undef short                            // get around bogus type defs.
00084 #undef int
00085 #undef long
00086 #endif // defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00087 
00088 
00089 #include <list> 
00090 using std::list;
00091 
00092 #endif // __SGI_STL_LIST_H
00093 
00094 
00095 #ifndef ERRORS_INCLUDED
00096 #include "errors.h"
00097 #endif // ERRORS_INCLUDED
00098 
00099 #ifndef mempool_INCLUDED
00100 #include "mempool.h"
00101 #endif // mempool_INCLUDED
00102 
00103 #ifndef segmented_array_INCLUDED
00104 #include "segmented_array.h"    // for SEGMENTED_ARRAY_ITERATOR
00105 #endif // segmented_array_INCLUDED
00106 
00107 #ifndef mempool_allocator_INCLUDED
00108 #include "mempool_allocator.h"
00109 #endif
00110 
00111 // ======================================================================
00112 // ======================================================================
00113 // A RELATED_SEGMENTED_ARRAY is a segmented array that can enter into
00114 // a particular kind of relationship with other
00115 // RELATED_SEGMENTED_ARRAYs. The particular relationship is this: When
00116 // one of the arrays (called the primary one) in the pair grows or
00117 // shrinks, the other one (called the secondary, or child, or kid) grows
00118 // automatically. The secondary array may be primary in relationships
00119 // of its own, in which case its child(ren) is (are) resized
00120 // automatically, etc.
00121 //
00122 // From the time that the relationship is established between two
00123 // segmented arrays until the relationship is dissolved, we maintain
00124 // the invariant that an index is a valid subscript for one of the
00125 // arrays if and only if it is a valid subscript for the other one.
00126 //
00127 // This invariant is maintained only "top-down"; if a
00128 // RELATED_SEGMENTED_ARRAY is a registered kid of another
00129 // RELATED_SEGMENTED_ARRAY, the behavior is undefined if the kid is
00130 // resized by some operation other than the automatic resizing that
00131 // takes place when its parent gets resized.
00132 //
00133 // To accomplish all this in a clean way, we apparently need some
00134 // dirty C++: inheritance!
00135 //
00136 // RELATED_SEGMENTED_ARRAYs are used in the compiler when we want to
00137 // maintain phase-specific tables alongside long-lived tables (usually
00138 // as part of the morass of tables we call the "symbol table"). For
00139 // example, the PREG_TAB lives throughout the compiler (front end
00140 // through code generator), and contains no representation of home
00141 // locations. In the back end, when we assign a home location to a
00142 // PREG, we store the home location information in a secondary table
00143 // of type BE_PREG_TAB. When we begin compiling a PU in the back end,
00144 // we register the BE_PREG_TAB with the PREG_TAB, establishing that
00145 // the PREG_TAB is primary and the BE_PREG_TAB is secondary in that
00146 // relationship. Then we are assured that the BE_PREG_TAB can be
00147 // indexed by exactly those indices that we use for the PREG_TAB. At
00148 // the beginning of the back end's work on each PU, the BE_PREG_TAB is
00149 // registered as a kid of the PREG_TAB using the routine
00150 // growing_table::Register; this registration is the beginning of the
00151 // relationship during which the secondary table (BE_PREG_TAB) is kept
00152 // in sync with all grow/shrink operations that affect the primary
00153 // table (PREG_TAB). The relationship ends when
00154 // growing_table::Un_register is called to dissociate the pair.
00155 //
00156 // A more complicated usage example arises when we want to maintain
00157 // some table in parallel with the multi-layered Symbol_Table
00158 // structure. For an example of how that's done in the F90 front end,
00159 // see mongoose/crayf90/sgi/cwh_stab.i, which declares an auxilliary
00160 // table indexed by ST_IDX and called AUXST_TABLE.
00161 //
00162 // Note that the class T used in RELATED_SEGMENTED_ARRAY should have a constructor
00163 // if it needs any initilization (i.e, be careful about RELATED_SEGMENTED_ARRAY<int> or
00164 // RELATED_SEGMENTED_ARRAY<FOO *>).
00165 //
00166 // ======================================================================
00167 // ======================================================================
00168 
00169 // TODO: Add assertions.
00170 //       Make block-growth more efficient.
00171 
00172 class growing_table {
00173 protected:
00174   UINT                  size;   // total number of elements present
00175 
00176 private:
00177 
00178   typedef std::list<growing_table *> kids_type;
00179 
00180   kids_type kids;       
00181   
00182   virtual void Construct_new_entry(void) = 0;
00183   virtual void Construct_new_entry(UINT n) = 0;
00184   virtual void Delete_last(void) = 0;
00185   virtual void Delete_last(UINT n) = 0;
00186 
00187 protected:
00188   // Here each RELATED_SEGMENTED_ARRAY member function that changes
00189   // the size is represented by a member function. Note that we
00190   // can represent only primitives that are independent of the
00191   // segmented array's base type, since this base class isn't (and
00192   // can't be) a template.
00193   void Decrease_kids_size(void)
00194     {
00195       for (kids_type::iterator kid = kids.begin();
00196            kid != kids.end();
00197            ++kid) {
00198         (*kid)->Delete_last();
00199       }
00200     }
00201 
00202   void Decrease_kids_size(UINT n)
00203     {
00204       for (kids_type::iterator kid = kids.begin();
00205            kid != kids.end();
00206            ++kid) {
00207         (*kid)->Delete_last(n);
00208       }
00209     }
00210 
00211   void Increase_kids_size(void)
00212     {
00213       for (kids_type::iterator kid = kids.begin();
00214            kid != kids.end();
00215            ++kid) {
00216         (*kid)->Construct_new_entry();
00217       }
00218     }
00219 
00220   void Increase_kids_size(UINT n)
00221     {
00222       for (kids_type::iterator kid = kids.begin();
00223            kid != kids.end();
00224            ++kid) {
00225         (*kid)->Construct_new_entry(n);
00226       }
00227     }
00228 
00229 public:
00230   growing_table() : size(0) { }
00231   virtual ~growing_table() { }
00232 
00233   // Here we have a member function to register a new kid with this
00234   // growing_table.
00235   void Register(growing_table &kid)
00236     {
00237       // Make sure the new kid is of the right size:
00238       FmtAssert(kid.size <= size,
00239                 ("growing_table::Register: child must not be larger "
00240                  "than parent"));
00241       // TODO: Cheesy, inefficient method for now.
00242       while (kid.size < size) {
00243         kid.Construct_new_entry();
00244       }
00245 
00246       // Put the new kid into the list of kids:
00247       kids.push_front(&kid);
00248     }
00249 
00250   void Un_register(growing_table &kid)
00251     {
00252       kids_type::iterator kid_ptr = std::find(kids.begin(), kids.end(), &kid);
00253       if (kid_ptr != kids.end()) {
00254         kids.erase(kid_ptr);
00255       }
00256       else {
00257         Fail_FmtAssertion("RELATED_SEGMENTED_ARRAY: Cannot un-register "
00258                           "an unregistered kid");
00259       }
00260     }
00261 };
00262 
00263 template <class T, UINT block_size = 128>
00264 class RELATED_SEGMENTED_ARRAY : public growing_table {
00265 private:
00266 
00267     std::vector<std::pair<T *, BOOL>, mempool_allocator<std::pair<T *,BOOL> > > map;
00268 
00269     MEM_POOL *pool;
00270     UINT max_size;                      // total # of elements allocated
00271     INT block_base;                     // idx of the beginning of
00272                                         // block (signed so we can set
00273                                         // to -1, meaning no block allocated)
00274     UINT next_block_size;               // size of block to be allocated
00275     T *block;                           // points to the last block
00276 
00277 private:
00278     
00279     typedef RELATED_SEGMENTED_ARRAY<T, block_size> self;
00280 
00281 public:
00282     typedef T base_type;
00283 
00284     typedef T                 value_type;
00285     typedef value_type*       pointer;
00286     typedef const value_type* const_pointer;
00287     typedef value_type&       reference;
00288     typedef const value_type& const_reference;
00289     typedef UINT              size_type;
00290     typedef INT               difference_type;
00291 
00292     typedef SEGMENTED_ARRAY_ITERATOR<self*, T, pointer, reference>
00293             iterator;
00294     typedef SEGMENTED_ARRAY_ITERATOR<const self*, T, 
00295                                      const_pointer, const_reference> 
00296             const_iterator;
00297 
00298 private:
00299     // private operations
00300 
00301     virtual void Construct_new_entry(void)
00302       {
00303         if (size == max_size) Allocate();
00304         Increase_kids_size();
00305         new(&block[size++ - block_base]) T(); // T() makes sure the
00306                                               // default constructor
00307                                               // is called. T without
00308                                               // parens would not
00309                                               // ensure this.
00310       }
00311 
00312     virtual void Construct_new_entry(UINT n)
00313       {
00314         // Cheesy implementation for now to get things working without
00315         // the risk of having to think.
00316         for (; n > 0; n--) {
00317           Construct_new_entry();
00318         }
00319       }
00320 
00321     UINT Round_up (UINT s) {
00322         UINT mask = block_size - 1;
00323         return (s + mask) & ~mask;
00324     }
00325 
00326     void Update_Map (T *marker, UINT new_size, BOOL own_memory);
00327 
00328     void Pop_Map ();
00329 
00330     // allocate a block, assume the array is completely filled
00331     void Allocate ();
00332 
00333     T& New_entry () {
00334 
00335         if (size == max_size) Allocate ();
00336         Increase_kids_size();
00337         return block[size++ - block_base];
00338     }
00339     
00340     // copy n elements to current buffer, assume no overflow
00341     void Copy (const T* x, UINT n) {
00342         std::copy(x, x + n, block + (size - block_base));
00343         size += n;
00344         Increase_kids_size(n);
00345     }
00346 
00347     // block_idx is an index into the map.  This function returns
00348     // the first map index that points to a different block. 
00349     UINT next_block_idx(UINT block_idx) const {
00350       for ( ; block_idx + 1 < map.size() &&
00351               map[block_idx].first + block_size == map[block_idx + 1].first;
00352             ++block_idx)
00353         {}
00354       return block_idx + 1;
00355     }
00356 
00357 public:
00358 
00359   RELATED_SEGMENTED_ARRAY(MEM_POOL *m = Malloc_Mem_Pool) : map(m), pool(m) {
00360       size = max_size = next_block_size = 0;
00361       block_base = -1;
00362       block = 0;
00363   }
00364 
00365   ~RELATED_SEGMENTED_ARRAY() {
00366     // Free memory from blocks. Map memory gets freed when the map
00367     // vector is destructed.
00368     typedef typename vector<pair<T *, BOOL>, mempool_allocator<pair<T *, BOOL> > >::iterator TempIteratorType;
00369     for ( TempIteratorType entry = map.begin(); entry != map.end(); ++entry ) {
00370       // entry->second <==> this map entry owns the block's memory.
00371       if (entry->second) {
00372         MEM_POOL_FREE(pool, entry->first);
00373       }
00374     }
00375   }
00376 
00377   UINT Block_size () const      { return block_size; }
00378 
00379   UINT Size () const            { return growing_table::size; }
00380 
00381   T& Entry (UINT idx) {
00382     Is_True (idx < size, ("Array subscript out of bound"));
00383     return map[idx / block_size].first[idx % block_size];
00384   }
00385 
00386   const T& Entry (UINT idx) const {
00387     Is_True (idx < size, ("Array subscript out of bound"));
00388     return map[idx / block_size].first[idx % block_size];
00389   }
00390 
00391 
00392   T& operator[] (UINT idx)             { return Entry(idx); }
00393   const T& operator[] (UINT idx) const { return Entry(idx); }
00394 
00395   iterator begin () {
00396     return iterator (this, map[0].first, Block_end (0), 0);
00397   }
00398 
00399   iterator end () {
00400     return iterator (this, block + (size - block_base),
00401                      block + (max_size - block_base), size);
00402   }
00403 
00404   const_iterator begin () const {
00405     return const_iterator (this, map[0].first, Block_end (0), 0);
00406   }
00407 
00408   const_iterator end () const {
00409     return const_iterator (this, block + (size - block_base),
00410                            block + (max_size - block_base), size);
00411   }
00412         
00413     T& New_entry (UINT& idx)    { idx = size; return New_entry (); }
00414 
00415     UINT Insert (const T& x);
00416 
00417     virtual void Delete_last () {
00418       size--;
00419       Decrease_kids_size();
00420       if (size == (UINT)block_base)
00421         Pop_Map ();
00422     }
00423 
00424     virtual void Delete_last (UINT n);
00425 
00426     // insert multiple elements, always copy to new buffer.
00427     UINT Insert (const T* x, UINT n_elemt);
00428     
00429     // similar to insert, except reuse the given buffer if possible
00430     UINT Transfer (T* x, UINT n_elemt);
00431     
00432     // Reserve extra storage.  Actual allocation will be done when the
00433     // already allocated storage is filled.
00434     void Reserve (UINT n_elemt) {
00435         if (max_size - size + next_block_size < n_elemt)
00436             next_block_size = n_elemt - (max_size - size);
00437     }
00438 
00439     // return the number of element till the end of the block
00440     UINT Get_block_size (UINT idx) const {
00441       UINT block_idx = idx / block_size;
00442       return min(next_block_idx(block_idx) * block_size, size) - idx;
00443     }
00444 
00445     UINT Block_index (UINT idx) const { return idx / block_size; }
00446 
00447     // A valid block index n is in the range 0 <= n < Block_index_end().
00448     UINT Block_index_end () const { return map.size(); }
00449 
00450     T* Block_begin (UINT block_idx)             { return map[block_idx].first; }
00451     const T* Block_begin (UINT block_idx) const { return map[block_idx].first; }
00452 
00453     T* Block_end(UINT block_idx) {
00454       return Block_begin(block_idx) +
00455              (next_block_idx(block_idx) - block_idx) * block_size;
00456     }
00457 
00458     const T* Block_end(UINT block_idx) const {
00459       return Block_begin(block_idx) +
00460              (next_block_idx(block_idx) - block_idx) * block_size;
00461     }
00462 
00463     void Clear(void);
00464 }; // RELATED_SEGMENTED_ARRAY
00465 
00466 template <class T, UINT block_size>
00467 inline void
00468 RELATED_SEGMENTED_ARRAY<T,block_size>::Update_Map(T    *marker,
00469                                                   UINT  new_size,
00470                                                   BOOL  own_memory)
00471 {
00472   do {
00473 
00474     map.push_back(std::pair<T*, BOOL>(marker, own_memory));
00475     new_size -= block_size;
00476     marker += block_size;
00477   } while (new_size);
00478 } // RELATED_SEGMENTED_ARRAY<T,block_size>::Update_Map
00479 
00480 
00481 // deallocate a block and re-adjust the map and other variables
00482 template <class T, UINT block_size>
00483 void
00484 RELATED_SEGMENTED_ARRAY<T,block_size>::Pop_Map ()
00485 {
00486     next_block_size += max_size - block_base;
00487     MEM_POOL_FREE (pool, block);
00488 
00489     T *last_map_entry;
00490     do {
00491       last_map_entry = (map.end() - 1)->first;
00492       map.pop_back ();
00493     } while (last_map_entry != block);
00494 
00495     max_size = size;
00496     if (size > 0) {
00497       Is_True(size >= block_size,
00498               ("RELATED_SEGMENTED_ARRAY: size in limbo"));
00499       block_base = size - block_size;
00500       UINT idx = block_base / block_size;
00501       block = map[idx].first;
00502       while (idx > 0 && map[idx - 1].first + block_size == block) {
00503         block = map[--idx].first;
00504         block_base -= block_size;
00505       }
00506     }
00507     else {
00508       Is_True(map.begin() == map.end(),
00509               ("RELATED_SEGMENTED_ARRAY::Pop_Map: Map should be empty"));
00510       block_base = -1;
00511       block = NULL;
00512     }
00513 } // RELATED_SEGMENTED_ARRAY<T,block_size>::Pop_Map
00514 
00515 
00516 template <class T, UINT block_size>
00517 void
00518 RELATED_SEGMENTED_ARRAY<T,block_size>::Allocate ()
00519 {
00520     Is_True (size == max_size, ("Invalid internal state in segmented array"));
00521 
00522     UINT new_size;
00523 
00524     if (next_block_size == 0)
00525         new_size = block_size;
00526     else {
00527         new_size = Round_up (next_block_size);
00528         next_block_size = 0;
00529     }
00530 
00531     block = (T *) MEM_POOL_Alloc (pool, new_size * sizeof(T));
00532     max_size += new_size;
00533     block_base = size;
00534 
00535     Update_Map (block, new_size, TRUE);
00536 
00537 } // RELATED_SEGMENTED_ARRAY::Allocate
00538 
00539 
00540 template <class T, UINT block_size>
00541 void
00542 RELATED_SEGMENTED_ARRAY<T,block_size>::Delete_last (UINT n)
00543 {
00544   while (n >= size - block_base) {
00545     n -= size - block_base;
00546     size = block_base;
00547     Pop_Map ();
00548   }
00549   size -= n;
00550   Decrease_kids_size(n);
00551 } // Delete_last
00552 
00553 
00554 template <class T, UINT block_size>
00555 inline UINT
00556 RELATED_SEGMENTED_ARRAY<T,block_size>::Insert (const T& x)
00557 {
00558     UINT idx = size;
00559     T &entry = New_entry ();
00560 
00561     entry = x;
00562     return idx;
00563 } // RELATED_SEGMENTED_ARRAY::Insert
00564 
00565 
00566 template <class T, UINT block_size>
00567 UINT
00568 RELATED_SEGMENTED_ARRAY<T,block_size>::Insert (const T* x, UINT n_elemt)
00569 {
00570     UINT result = size;
00571     if (size + n_elemt <= max_size) {
00572         Copy (x, n_elemt);
00573         return result;
00574     }
00575 
00576     UINT space_left = max_size - size;
00577     Copy (x, space_left);
00578     n_elemt -= space_left;
00579 
00580     Reserve (n_elemt);
00581     Allocate ();
00582     Copy (x + space_left, n_elemt);
00583 
00584     return result;
00585 } // RELATED_SEGMENTED_ARRAY::Insert
00586 
00587 
00588 template <class T, UINT block_size>
00589 UINT
00590 RELATED_SEGMENTED_ARRAY<T,block_size>::Transfer (T* x, UINT n_elemt)
00591 {
00592     UINT result = size;
00593 
00594     if (size + n_elemt <= max_size) {
00595         Copy (x, n_elemt);
00596         return result;
00597     }
00598 
00599     UINT space_left = max_size - size;
00600     if (space_left > 0) {
00601         Copy (x, space_left);
00602         n_elemt -= space_left;
00603         x += space_left;
00604     }
00605 
00606     if (n_elemt >= block_size) {
00607         UINT reused_size = n_elemt & ~(block_size - 1);
00608         block = x;
00609         Update_Map (block, reused_size, FALSE);
00610         block_base = size;
00611         size += reused_size;
00612         max_size += reused_size;
00613         n_elemt -= reused_size;
00614         x += reused_size;
00615         if (next_block_size > reused_size)
00616             next_block_size -= reused_size;
00617         else
00618             next_block_size = 0;
00619     }
00620 
00621     if (n_elemt > 0) {
00622         Allocate ();
00623         Copy (x, n_elemt);
00624     }
00625 
00626     return result;
00627 } // RELATED_SEGMENTED_ARRAY::Transfer
00628 
00629 // Release all resources and return the RELATED_SEGMENTED_ARRAY to a
00630 // pristine state.
00631 template <class T, UINT block_size>
00632 void
00633 RELATED_SEGMENTED_ARRAY<T,block_size>::Clear(void)
00634 {
00635   if (growing_table::size > 0) {
00636     Delete_last(growing_table::size);
00637   }
00638   Is_True(map.begin() == map.end(),
00639           ("RELATED_SEGMENTED_ARRAY::Clear: Map should be empty"));
00640 }
00641 
00642 template <class T, UINT block_size, class OP>
00643 inline void
00644 For_all_entries (RELATED_SEGMENTED_ARRAY<T, block_size>& array,
00645                  const OP &op,
00646                  UINT32 first = 0)
00647 {
00648     UINT last = array.Size ();
00649 
00650     while (first < last) {
00651         T *block = &array[first];
00652         UINT size = array.Get_block_size (first);
00653         for (UINT j = 0; j < size; ++j, ++block)
00654             op (first + j, block);
00655         first += size;
00656     }
00657 }
00658 
00659 // The following function is ifdefed out because, until we have
00660 // partial ordering of function templates, the compiler will flag it
00661 // as ambiguous.
00662 #if 0
00663 
00664 template <class T, UINT block_size, class OP>
00665 inline void
00666 For_all_entries (const RELATED_SEGMENTED_ARRAY<T, block_size>& array,
00667                  const OP &op,
00668                  UINT32 first = 0)
00669 {
00670     UINT last = array.Size ();
00671 
00672     while (first < last) {
00673         const T *block = &array[first];
00674         UINT size = array.Get_block_size (first);
00675         for (UINT j = 0; j < size; ++j, ++block)
00676             op (first + j, block);
00677         first += size;
00678     }
00679 }
00680 
00681 #endif
00682 
00683 template <class T, UINT block_size, class OP>
00684 inline void
00685 For_all_blocks (RELATED_SEGMENTED_ARRAY<T, block_size>& array, const OP &op)
00686 {
00687     UINT max_size = array.Size ();
00688     UINT i = 0;
00689 
00690     while (i < max_size) {
00691         T *block = &array[i];
00692         UINT size = array.Get_block_size (i);
00693         op (i, block, size);
00694         i += size;
00695     }
00696 }
00697 
00698 
00699 #define NOT_FOUND ((UINT) -1)
00700 
00701 template <class T, UINT block_size, class PREDICATE>
00702 inline UINT
00703 Find_entry_if (const RELATED_SEGMENTED_ARRAY<T, block_size>& array,
00704                const PREDICATE& pred, UINT i = 0)
00705 {
00706     UINT max_size = array.Size ();
00707 
00708     while (i < max_size) {
00709         const T *block = &array[i];
00710         UINT size = array.Get_block_size (i);
00711         for (UINT j = 0; j < size; ++j, ++block)
00712             if (pred (i+j, block))
00713                 return i + j;
00714         i += size;
00715     }
00716 
00717     return (UINT) NOT_FOUND;
00718 }
00719 
00720 
00721 // copy the content of one segmented array to another, optionally specified
00722 // the range [first_idx, last_idx) to be copied.
00723 // returns the number of entries copied.
00724 template <class T, UINT block_size>
00725 UINT32
00726 Copy_array_range (const RELATED_SEGMENTED_ARRAY<T, block_size>& from_array,
00727                   RELATED_SEGMENTED_ARRAY<T, block_size>& to_array,
00728                   UINT32 first_idx = 0, UINT32 last_idx = (UINT32) -1)
00729 {
00730     if (last_idx > from_array.Size ())
00731         last_idx = from_array.Size ();
00732 
00733     Is_True (last_idx >= first_idx, ("Invalid copy range"));
00734 
00735     UINT32 entries = last_idx - first_idx;
00736 
00737     to_array.Reserve (entries);
00738 
00739     while (first_idx < last_idx) {
00740         const T* block = &from_array[first_idx];
00741         UINT32 size = from_array.Get_block_size (first_idx);
00742         if (size > last_idx - first_idx)
00743             size = last_idx - first_idx;
00744 
00745         to_array.Insert (block, size);
00746         first_idx += size;
00747     }
00748 
00749     return entries;
00750 } // Copy_array_range
00751 
00752 #endif // cmplr_segmented_array_INCLUDED
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines