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 /* ==================================================================== 00037 * ==================================================================== 00038 * 00039 * 00040 * Description: 00041 * 00042 * Priority queue implementation 00043 * 00044 * ==================================================================== 00045 * ==================================================================== 00046 */ 00047 00048 #include "defs.h" 00049 #include "errors.h" 00050 #include "mempool.h" 00051 #include "priority_queue.h" 00052 00057 #define PRQ_comparison_fn(x) ((x)->comparison_fn) 00058 #define PRQ_mem_pool(x) ((x)->mem_pool) 00059 #define PRQ_size(x) ((x)->size) 00060 #define PRQ_allocated_size(x) ((x)->allocated_size) 00061 #define PRQ_expansion_factor(x) ((x)->expansion_factor) 00062 #define PRQ_get_index_fn(x) ((x)->get_index_fn) 00063 #define PRQ_set_index_fn(x) ((x)->set_index_fn) 00064 #define PRQ_heap_vector(x) ((x)->heap_vector) 00065 00066 00072 /* ======================================================================= 00073 * 00074 * PRQ_Ith 00075 * 00076 * See interface description. 00077 * 00078 * ======================================================================= 00079 */ 00080 void* 00081 PRQ_Ith( 00082 PRQ* prq, 00083 INT32 i 00084 ) 00085 { 00086 return PRQ_heap_vector(prq)[i-1]; 00087 } 00088 00089 /* ======================================================================= 00090 * 00091 * PRQ_Set_Ith 00092 * 00093 * See interface description. 00094 * 00095 * ======================================================================= 00096 */ 00097 extern INT32 00098 PRQ_Size( 00099 PRQ* prq 00100 ) 00101 { 00102 return PRQ_size(prq); 00103 } 00104 00105 /* ======================================================================= 00106 * 00107 * PRQ_Set_Ith 00108 * 00109 * Make 'element' the 'i'-th element of 'prq'. 00110 * 00111 * ======================================================================= 00112 */ 00113 static void 00114 PRQ_Set_Ith( 00115 PRQ* prq, 00116 INT32 i, 00117 void* element 00118 ) 00119 { 00120 if ( PRQ_set_index_fn(prq) != NULL ) { 00121 PRQ_set_index_fn(prq)(element,i); 00122 } 00123 00124 PRQ_heap_vector(prq)[i-1] = element; 00125 } 00126 00127 00137 /* ======================================================================= 00138 * 00139 * PRQ_Upheap 00140 * 00141 * Sifts the heap_element at position 'index' in the heap (1-based) up to 00142 * its appropriate position in the heap. If the heap element should not 00143 * move closer to the root ("up"), it is not moved. The the new index of 00144 * the heap_element is returned. 00145 * 00146 * ======================================================================= 00147 */ 00148 static INT32 00149 PRQ_Upheap( 00150 PRQ* prq, 00151 INT32 index 00152 ) 00153 { 00154 void* element; 00155 00156 FmtAssert(index <= PRQ_size(prq) && index > 0, 00157 ("PRQ_Upheap: index %d out of bounds %d", 00158 index,PRQ_size(prq))); 00159 00160 element = PRQ_Ith(prq,index); 00161 00162 /* Note we do not perform a complete interchange in the body of the 00163 * loop. We wait until we have found the correct position for 00164 * 'element' before setting it. 00165 */ 00166 while ( index > 1 ) { 00167 INT32 parent_index = index / 2; 00168 void* parent = PRQ_Ith(prq,parent_index); 00169 00170 if ( ! PRQ_comparison_fn(prq)(element,parent) ) 00171 break; 00172 00173 PRQ_Set_Ith(prq,index,parent); 00174 index = parent_index; 00175 } 00176 00177 PRQ_Set_Ith(prq,index,element); 00178 00179 return index; 00180 } 00181 00182 00183 /* ======================================================================= 00184 * 00185 * PRQ_Downheap 00186 * 00187 * Sifts the heap element at position 'index' in the heap (1-based) down 00188 * to its appropriate position in the heap. If the heap element should 00189 * not move further from the root ("down"), it is not moved. The the new 00190 * index of the heap_element is returned. 00191 * 00192 * ======================================================================= 00193 */ 00194 static INT32 00195 PRQ_Downheap( 00196 PRQ* prq, 00197 INT32 index 00198 ) 00199 { 00200 void* element; 00201 00202 FmtAssert(index <= PRQ_size(prq) && index > 0, 00203 ("PRQ_down: index %d out of bounds %d", 00204 index,PRQ_size(prq))); 00205 00206 element = PRQ_Ith(prq,index); 00207 00208 /* Note we do not perform a complete interchange in the body of the 00209 * loop. We wait until we have found the correct position for 00210 * 'element' before setting it. 00211 */ 00212 00213 for(;;) { 00214 void* left_child; 00215 INT32 left_child_index = index * 2; 00216 INT32 right_child_index = left_child_index + 1; 00217 00218 if ( left_child_index > PRQ_size(prq) ) break; 00219 00220 left_child = PRQ_Ith(prq,left_child_index); 00221 00222 /* If the right child is in the heap, and is "larger" than the left, 00223 * try to interchange 'element' with the right child. If the 00224 * interchange test fails, 'index' is the correct position for 00225 * element. 00226 */ 00227 if ( right_child_index <= PRQ_size(prq) 00228 && PRQ_comparison_fn(prq)(PRQ_Ith(prq,right_child_index), 00229 left_child) 00230 ) { 00231 void* right_child = PRQ_Ith(prq,right_child_index); 00232 00233 if ( PRQ_comparison_fn(prq)(right_child,element) ) { 00234 PRQ_Set_Ith(prq,index,right_child); 00235 index = right_child_index; 00236 } 00237 else 00238 break; 00239 } 00240 else if ( PRQ_comparison_fn(prq)(left_child,element) ) { 00241 /* interchange with left child */ 00242 PRQ_Set_Ith(prq,index,left_child); 00243 index = left_child_index; 00244 } 00245 else 00246 break; 00247 } 00248 00249 PRQ_Set_Ith(prq,index,element); 00250 00251 return index; 00252 } 00253 00254 00261 /* ======================================================================= 00262 * 00263 * PRQ_Initialize 00264 * 00265 * See interface description. 00266 * 00267 * ======================================================================= 00268 */ 00269 void 00270 PRQ_Initialize( 00271 PRQ* prq, 00272 PRQ_COMPARISON_FUNCTION comparison_fn, 00273 PRQ_GET_INDEX_FUNCTION get_fn, 00274 PRQ_SET_INDEX_FUNCTION set_fn, 00275 MEM_POOL* pool, 00276 INT32 initial_size, 00277 INT32 expansion_factor 00278 ) 00279 { 00280 if ( initial_size <= 0 ) { 00281 DevWarn("Non positive priority queue initial size %d. Using 200", 00282 initial_size); 00283 initial_size = 200; 00284 } 00285 00286 if ( expansion_factor <= 100 ) { 00287 DevWarn("Priority queue expansion factor should be at least 100. " 00288 "Was %d using 200",expansion_factor); 00289 expansion_factor = 200; 00290 } 00291 00292 PRQ_comparison_fn(prq) = comparison_fn; 00293 PRQ_get_index_fn(prq) = get_fn; 00294 PRQ_set_index_fn(prq) = set_fn; 00295 PRQ_mem_pool(prq) = pool; 00296 PRQ_size(prq) = 0; 00297 PRQ_allocated_size(prq) = initial_size; 00298 PRQ_expansion_factor(prq) = expansion_factor; 00299 PRQ_heap_vector(prq) = TYPE_MEM_POOL_ALLOC_N(void*,pool,initial_size); 00300 } 00301 00302 00303 /* ======================================================================= 00304 * 00305 * PRQ_DeleteTop 00306 * 00307 * See interface description. 00308 * 00309 * ======================================================================= 00310 */ 00311 void* 00312 PRQ_Delete_Top( PRQ* prq ) 00313 { 00314 void* top_element; 00315 00316 FmtAssert(PRQ_size(prq) > 0,("Deleting from empty heap")); 00317 00318 top_element = PRQ_Ith(prq,1); 00319 if ( PRQ_size(prq) == 1 ) 00320 PRQ_size(prq) = 0; 00321 else { 00322 /* Move the bottom element to the top nad sift it down to its proper 00323 * position in the heap. 00324 */ 00325 void* bottom_element = PRQ_Ith(prq,PRQ_size(prq)); 00326 00327 --PRQ_size(prq); 00328 PRQ_Set_Ith(prq,1,bottom_element); 00329 (void) PRQ_Downheap(prq,1); 00330 } 00331 00332 return top_element; 00333 } 00334 00335 00336 00337 /* ======================================================================= 00338 * 00339 * PRQ_Top 00340 * 00341 * See interface description. 00342 * 00343 * ======================================================================= 00344 */ 00345 void* 00346 PRQ_Top( PRQ* prq ) 00347 { 00348 FmtAssert(PRQ_size(prq) > 0,("Topping empty queue")); 00349 00350 return PRQ_Ith(prq,1); 00351 } 00352 00353 00354 /* ======================================================================= 00355 * 00356 * PRQ_InsertElement 00357 * 00358 * See interface description. 00359 * 00360 * ======================================================================= 00361 */ 00362 void 00363 PRQ_Insert( 00364 PRQ* prq, 00365 void* element 00366 ) 00367 { 00368 /* Grow 'heap_vector' if necessary. 00369 */ 00370 if ( PRQ_size(prq) == PRQ_allocated_size(prq) ) { 00371 INT32 new_size = (PRQ_size(prq) * PRQ_expansion_factor(prq)) / 100; 00372 00373 if ( new_size <= PRQ_size(prq) ) { 00374 DevWarn("Priority queue expansion failed -- forcing expansion by 10"); 00375 new_size = PRQ_size(prq) + 10; 00376 } 00377 00378 PRQ_heap_vector(prq) = 00379 TYPE_MEM_POOL_REALLOC_N(void*,PRQ_mem_pool(prq),PRQ_heap_vector(prq), 00380 PRQ_allocated_size(prq), 00381 new_size); 00382 PRQ_allocated_size(prq) = new_size; 00383 } 00384 00385 /* Add element to bottom of heap, and sift it up to its appropriate 00386 * position. 00387 */ 00388 ++PRQ_size(prq); 00389 PRQ_Set_Ith(prq,PRQ_size(prq),element); 00390 (void) PRQ_Upheap(prq,PRQ_size(prq)); 00391 } 00392 00393 00394 /* ======================================================================= 00395 * 00396 * PRQ_RemoveElement 00397 * 00398 * See interface description. 00399 * 00400 * ======================================================================= 00401 */ 00402 void 00403 PRQ_Remove( 00404 PRQ* prq, 00405 void* element 00406 ) 00407 { 00408 INT32 index = UNDEFINED; 00409 00410 FmtAssert(PRQ_size(prq) > 0,("PRQ_RemoveElement -- empty queue")); 00411 00412 /* Find the index of 'element' in the heap.If we have an index function, 00413 * we can get the index of the element directly. Otherwise we search 00414 * for it. 00415 */ 00416 00417 if ( PRQ_get_index_fn(prq) ) { 00418 index = PRQ_get_index_fn(prq)(element); 00419 FmtAssert(element == PRQ_Ith(prq,index), 00420 ("Invalid priority queue index %d",index)); 00421 } 00422 else { 00423 INT32 i; 00424 00425 for ( i = 1; i <= PRQ_size(prq); ++i ) { 00426 if ( PRQ_Ith(prq,i) == element ) { 00427 index = i; 00428 break; 00429 } 00430 } 00431 } 00432 00433 FmtAssert(index != UNDEFINED,("Remove a PRQ element not in queue")); 00434 00435 /* If element is the bottom elment in the heap, simply decrement the 00436 * size, and we are done. 00437 */ 00438 if ( index == PRQ_size(prq) ) 00439 --PRQ_size(prq); 00440 else { 00441 /* Replace 'element' at position 'index' with the bottom element of 00442 * the heap. Then try to sift the newly placed 'bottom_element' up 00443 * and then down,to make sure it is in its correct position. 00444 */ 00445 void* bottom_element = PRQ_Ith(prq,PRQ_size(prq)); 00446 00447 /* Reposition bottom_element. 00448 */ 00449 --PRQ_size(prq); 00450 PRQ_Set_Ith(prq,index,bottom_element); 00451 00452 /* Try to move it up. If it moves we know it has found its 00453 * appropriate position. Otherwise, try to move it down. 00454 */ 00455 if ( index == PRQ_Upheap(prq,index) ) 00456 (void) PRQ_Downheap(prq,index); 00457 } 00458 } 00459 00460 00461 /* ======================================================================= 00462 * 00463 * PRQ_Reset 00464 * 00465 * See interface description. 00466 * 00467 * ======================================================================= 00468 */ 00469 void 00470 PRQ_Reset( PRQ* prq ) 00471 { 00472 PRQ_size(prq) = 0; 00473 }