1f220fa62Smrg/* 2f220fa62Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) 3f220fa62Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. 4f220fa62Smrg * 5f220fa62Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6f220fa62Smrg * copy of this software and associated documentation files (the "Software"), 7f220fa62Smrg * to deal in the Software without restriction, including without limitation 8f220fa62Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9f220fa62Smrg * and/or sell copies of the Software, and to permit persons to whom the 10f220fa62Smrg * Software is furnished to do so, subject to the following conditions: 11f220fa62Smrg * 12f220fa62Smrg * The above copyright notice including the dates of first publication and 13f220fa62Smrg * either this permission notice or a reference to 14f220fa62Smrg * http://oss.sgi.com/projects/FreeB/ 15f220fa62Smrg * shall be included in all copies or substantial portions of the Software. 16f220fa62Smrg * 17f220fa62Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18f220fa62Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19f220fa62Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20f220fa62Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21f220fa62Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 22f220fa62Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23f220fa62Smrg * SOFTWARE. 24f220fa62Smrg * 25f220fa62Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc. 26f220fa62Smrg * shall not be used in advertising or otherwise to promote the sale, use or 27f220fa62Smrg * other dealings in this Software without prior written authorization from 28f220fa62Smrg * Silicon Graphics, Inc. 29f220fa62Smrg */ 30f220fa62Smrg/* 31f220fa62Smrg** Author: Eric Veach, July 1994. 32f220fa62Smrg** 33f220fa62Smrg*/ 34f220fa62Smrg 35f220fa62Smrg#include <stddef.h> 36f220fa62Smrg#include <assert.h> 37f220fa62Smrg#include "priorityq-heap.h" 38f220fa62Smrg#include "memalloc.h" 39f220fa62Smrg 40f220fa62Smrg#define INIT_SIZE 32 41f220fa62Smrg 42f220fa62Smrg#ifndef TRUE 43f220fa62Smrg#define TRUE 1 44f220fa62Smrg#endif 45f220fa62Smrg#ifndef FALSE 46f220fa62Smrg#define FALSE 0 47f220fa62Smrg#endif 48f220fa62Smrg 49f220fa62Smrg#ifdef FOR_TRITE_TEST_PROGRAM 50f220fa62Smrg#define LEQ(x,y) (*pq->leq)(x,y) 51f220fa62Smrg#else 52f220fa62Smrg/* Violates modularity, but a little faster */ 53f220fa62Smrg#include "geom.h" 54f220fa62Smrg#define LEQ(x,y) VertLeq((GLUvertex *)x, (GLUvertex *)y) 55f220fa62Smrg#endif 56f220fa62Smrg 57f220fa62Smrg/* really __gl_pqHeapNewPriorityQ */ 58f220fa62SmrgPriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) ) 59f220fa62Smrg{ 60f220fa62Smrg PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ )); 61f220fa62Smrg if (pq == NULL) return NULL; 62f220fa62Smrg 63f220fa62Smrg pq->size = 0; 64f220fa62Smrg pq->max = INIT_SIZE; 65f220fa62Smrg pq->nodes = (PQnode *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->nodes[0]) ); 66f220fa62Smrg if (pq->nodes == NULL) { 67f220fa62Smrg memFree(pq); 68f220fa62Smrg return NULL; 69f220fa62Smrg } 70f220fa62Smrg 71f220fa62Smrg pq->handles = (PQhandleElem *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->handles[0]) ); 72f220fa62Smrg if (pq->handles == NULL) { 73f220fa62Smrg memFree(pq->nodes); 74f220fa62Smrg memFree(pq); 75f220fa62Smrg return NULL; 76f220fa62Smrg } 77f220fa62Smrg 78f220fa62Smrg pq->initialized = FALSE; 79f220fa62Smrg pq->freeList = 0; 80f220fa62Smrg pq->leq = leq; 81f220fa62Smrg 82f220fa62Smrg pq->nodes[1].handle = 1; /* so that Minimum() returns NULL */ 83f220fa62Smrg pq->handles[1].key = NULL; 84f220fa62Smrg return pq; 85f220fa62Smrg} 86f220fa62Smrg 87f220fa62Smrg/* really __gl_pqHeapDeletePriorityQ */ 88f220fa62Smrgvoid pqDeletePriorityQ( PriorityQ *pq ) 89f220fa62Smrg{ 90f220fa62Smrg memFree( pq->handles ); 91f220fa62Smrg memFree( pq->nodes ); 92f220fa62Smrg memFree( pq ); 93f220fa62Smrg} 94f220fa62Smrg 95f220fa62Smrg 96f220fa62Smrgstatic void FloatDown( PriorityQ *pq, long curr ) 97f220fa62Smrg{ 98f220fa62Smrg PQnode *n = pq->nodes; 99f220fa62Smrg PQhandleElem *h = pq->handles; 100f220fa62Smrg PQhandle hCurr, hChild; 101f220fa62Smrg long child; 102f220fa62Smrg 103f220fa62Smrg hCurr = n[curr].handle; 104f220fa62Smrg for( ;; ) { 105f220fa62Smrg child = curr << 1; 106f220fa62Smrg if( child < pq->size && LEQ( h[n[child+1].handle].key, 107f220fa62Smrg h[n[child].handle].key )) { 108f220fa62Smrg ++child; 109f220fa62Smrg } 110f220fa62Smrg 111f220fa62Smrg assert(child <= pq->max); 112f220fa62Smrg 113f220fa62Smrg hChild = n[child].handle; 114f220fa62Smrg if( child > pq->size || LEQ( h[hCurr].key, h[hChild].key )) { 115f220fa62Smrg n[curr].handle = hCurr; 116f220fa62Smrg h[hCurr].node = curr; 117f220fa62Smrg break; 118f220fa62Smrg } 119f220fa62Smrg n[curr].handle = hChild; 120f220fa62Smrg h[hChild].node = curr; 121f220fa62Smrg curr = child; 122f220fa62Smrg } 123f220fa62Smrg} 124f220fa62Smrg 125f220fa62Smrg 126f220fa62Smrgstatic void FloatUp( PriorityQ *pq, long curr ) 127f220fa62Smrg{ 128f220fa62Smrg PQnode *n = pq->nodes; 129f220fa62Smrg PQhandleElem *h = pq->handles; 130f220fa62Smrg PQhandle hCurr, hParent; 131f220fa62Smrg long parent; 132f220fa62Smrg 133f220fa62Smrg hCurr = n[curr].handle; 134f220fa62Smrg for( ;; ) { 135f220fa62Smrg parent = curr >> 1; 136f220fa62Smrg hParent = n[parent].handle; 137f220fa62Smrg if( parent == 0 || LEQ( h[hParent].key, h[hCurr].key )) { 138f220fa62Smrg n[curr].handle = hCurr; 139f220fa62Smrg h[hCurr].node = curr; 140f220fa62Smrg break; 141f220fa62Smrg } 142f220fa62Smrg n[curr].handle = hParent; 143f220fa62Smrg h[hParent].node = curr; 144f220fa62Smrg curr = parent; 145f220fa62Smrg } 146f220fa62Smrg} 147f220fa62Smrg 148f220fa62Smrg/* really __gl_pqHeapInit */ 149f220fa62Smrgvoid pqInit( PriorityQ *pq ) 150f220fa62Smrg{ 151f220fa62Smrg long i; 152f220fa62Smrg 153f220fa62Smrg /* This method of building a heap is O(n), rather than O(n lg n). */ 154f220fa62Smrg 155f220fa62Smrg for( i = pq->size; i >= 1; --i ) { 156f220fa62Smrg FloatDown( pq, i ); 157f220fa62Smrg } 158f220fa62Smrg pq->initialized = TRUE; 159f220fa62Smrg} 160f220fa62Smrg 161f220fa62Smrg/* really __gl_pqHeapInsert */ 162f220fa62Smrg/* returns LONG_MAX iff out of memory */ 163f220fa62SmrgPQhandle pqInsert( PriorityQ *pq, PQkey keyNew ) 164f220fa62Smrg{ 165f220fa62Smrg long curr; 166f220fa62Smrg PQhandle free_handle; 167f220fa62Smrg 168f220fa62Smrg curr = ++ pq->size; 169f220fa62Smrg if( (curr*2) > pq->max ) { 170f220fa62Smrg PQnode *saveNodes= pq->nodes; 171f220fa62Smrg PQhandleElem *saveHandles= pq->handles; 172f220fa62Smrg 173f220fa62Smrg /* If the heap overflows, double its size. */ 174f220fa62Smrg pq->max <<= 1; 175f220fa62Smrg pq->nodes = (PQnode *)memRealloc( pq->nodes, 176f220fa62Smrg (size_t) 177f220fa62Smrg ((pq->max + 1) * sizeof( pq->nodes[0] ))); 178f220fa62Smrg if (pq->nodes == NULL) { 179f220fa62Smrg pq->nodes = saveNodes; /* restore ptr to free upon return */ 180f220fa62Smrg return LONG_MAX; 181f220fa62Smrg } 182f220fa62Smrg pq->handles = (PQhandleElem *)memRealloc( pq->handles, 183f220fa62Smrg (size_t) 184f220fa62Smrg ((pq->max + 1) * 185f220fa62Smrg sizeof( pq->handles[0] ))); 186f220fa62Smrg if (pq->handles == NULL) { 187f220fa62Smrg pq->handles = saveHandles; /* restore ptr to free upon return */ 188f220fa62Smrg return LONG_MAX; 189f220fa62Smrg } 190f220fa62Smrg } 191f220fa62Smrg 192f220fa62Smrg if( pq->freeList == 0 ) { 193f220fa62Smrg free_handle = curr; 194f220fa62Smrg } else { 195f220fa62Smrg free_handle = pq->freeList; 196f220fa62Smrg pq->freeList = pq->handles[free_handle].node; 197f220fa62Smrg } 198f220fa62Smrg 199f220fa62Smrg pq->nodes[curr].handle = free_handle; 200f220fa62Smrg pq->handles[free_handle].node = curr; 201f220fa62Smrg pq->handles[free_handle].key = keyNew; 202f220fa62Smrg 203f220fa62Smrg if( pq->initialized ) { 204f220fa62Smrg FloatUp( pq, curr ); 205f220fa62Smrg } 206f220fa62Smrg assert(free_handle != LONG_MAX); 207f220fa62Smrg return free_handle; 208f220fa62Smrg} 209f220fa62Smrg 210f220fa62Smrg/* really __gl_pqHeapExtractMin */ 211f220fa62SmrgPQkey pqExtractMin( PriorityQ *pq ) 212f220fa62Smrg{ 213f220fa62Smrg PQnode *n = pq->nodes; 214f220fa62Smrg PQhandleElem *h = pq->handles; 215f220fa62Smrg PQhandle hMin = n[1].handle; 216f220fa62Smrg PQkey min = h[hMin].key; 217f220fa62Smrg 218f220fa62Smrg if( pq->size > 0 ) { 219f220fa62Smrg n[1].handle = n[pq->size].handle; 220f220fa62Smrg h[n[1].handle].node = 1; 221f220fa62Smrg 222f220fa62Smrg h[hMin].key = NULL; 223f220fa62Smrg h[hMin].node = pq->freeList; 224f220fa62Smrg pq->freeList = hMin; 225f220fa62Smrg 226f220fa62Smrg if( -- pq->size > 0 ) { 227f220fa62Smrg FloatDown( pq, 1 ); 228f220fa62Smrg } 229f220fa62Smrg } 230f220fa62Smrg return min; 231f220fa62Smrg} 232f220fa62Smrg 233f220fa62Smrg/* really __gl_pqHeapDelete */ 234f220fa62Smrgvoid pqDelete( PriorityQ *pq, PQhandle hCurr ) 235f220fa62Smrg{ 236f220fa62Smrg PQnode *n = pq->nodes; 237f220fa62Smrg PQhandleElem *h = pq->handles; 238f220fa62Smrg long curr; 239f220fa62Smrg 240f220fa62Smrg assert( hCurr >= 1 && hCurr <= pq->max && h[hCurr].key != NULL ); 241f220fa62Smrg 242f220fa62Smrg curr = h[hCurr].node; 243f220fa62Smrg n[curr].handle = n[pq->size].handle; 244f220fa62Smrg h[n[curr].handle].node = curr; 245f220fa62Smrg 246f220fa62Smrg if( curr <= -- pq->size ) { 247f220fa62Smrg if( curr <= 1 || LEQ( h[n[curr>>1].handle].key, h[n[curr].handle].key )) { 248f220fa62Smrg FloatDown( pq, curr ); 249f220fa62Smrg } else { 250f220fa62Smrg FloatUp( pq, curr ); 251f220fa62Smrg } 252f220fa62Smrg } 253f220fa62Smrg h[hCurr].key = NULL; 254f220fa62Smrg h[hCurr].node = pq->freeList; 255f220fa62Smrg pq->freeList = hCurr; 256f220fa62Smrg} 257