Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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