2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
31 ** Author: Eric Veach, July 1994.
37 #include <limits.h> /* LONG_MAX */
43 /* Include all the code for the regular heap-based queue here. */
45 typedef struct PriorityQHeap PriorityQHeap
;
46 typedef struct { PQhandle handle
; } PQnode
;
47 typedef struct { PQkey key
; PQhandle node
; } PQhandleElem
;
49 struct PriorityQHeap
{
51 PQhandleElem
*handles
;
55 int (*leq
)(PQkey key1
, PQkey key2
);
58 #define __gl_pqHeapMinimum(pq) ((pq)->handles[(pq)->nodes[1].handle].key)
59 #define __gl_pqHeapIsEmpty(pq) ((pq)->size == 0)
63 /* Violates modularity, but a little faster */
64 #define LEQ(x,y) VertLeq((GLUvertex *)x, (GLUvertex *)y)
66 static PriorityQHeap
*__gl_pqHeapNewPriorityQ( int (*leq
)(PQkey key1
, PQkey key2
) )
68 PriorityQHeap
*pq
= HeapAlloc( GetProcessHeap(), 0, sizeof( PriorityQHeap
));
69 if (pq
== NULL
) return NULL
;
73 pq
->nodes
= HeapAlloc( GetProcessHeap(), 0, (INIT_SIZE
+ 1) * sizeof(pq
->nodes
[0]) );
74 if (pq
->nodes
== NULL
) {
75 HeapFree( GetProcessHeap(), 0, pq
);
79 pq
->handles
= HeapAlloc( GetProcessHeap(), 0, (INIT_SIZE
+ 1) * sizeof(pq
->handles
[0]) );
80 if (pq
->handles
== NULL
) {
81 HeapFree( GetProcessHeap(), 0, pq
->nodes
);
82 HeapFree( GetProcessHeap(), 0, pq
);
86 pq
->initialized
= FALSE
;
90 pq
->nodes
[1].handle
= 1; /* so that Minimum() returns NULL */
91 pq
->handles
[1].key
= NULL
;
95 static void __gl_pqHeapDeletePriorityQ( PriorityQHeap
*pq
)
97 HeapFree( GetProcessHeap(), 0, pq
->handles
);
98 HeapFree( GetProcessHeap(), 0, pq
->nodes
);
99 HeapFree( GetProcessHeap(), 0, pq
);
103 static void FloatDown( PriorityQHeap
*pq
, long curr
)
105 PQnode
*n
= pq
->nodes
;
106 PQhandleElem
*h
= pq
->handles
;
107 PQhandle hCurr
, hChild
;
110 hCurr
= n
[curr
].handle
;
113 if( child
< pq
->size
&& LEQ( h
[n
[child
+1].handle
].key
,
114 h
[n
[child
].handle
].key
)) {
118 assert(child
<= pq
->max
);
120 hChild
= n
[child
].handle
;
121 if( child
> pq
->size
|| LEQ( h
[hCurr
].key
, h
[hChild
].key
)) {
122 n
[curr
].handle
= hCurr
;
123 h
[hCurr
].node
= curr
;
126 n
[curr
].handle
= hChild
;
127 h
[hChild
].node
= curr
;
133 static void FloatUp( PriorityQHeap
*pq
, long curr
)
135 PQnode
*n
= pq
->nodes
;
136 PQhandleElem
*h
= pq
->handles
;
137 PQhandle hCurr
, hParent
;
140 hCurr
= n
[curr
].handle
;
143 hParent
= n
[parent
].handle
;
144 if( parent
== 0 || LEQ( h
[hParent
].key
, h
[hCurr
].key
)) {
145 n
[curr
].handle
= hCurr
;
146 h
[hCurr
].node
= curr
;
149 n
[curr
].handle
= hParent
;
150 h
[hParent
].node
= curr
;
155 static void __gl_pqHeapInit( PriorityQHeap
*pq
)
159 /* This method of building a heap is O(n), rather than O(n lg n). */
161 for( i
= pq
->size
; i
>= 1; --i
) {
164 pq
->initialized
= TRUE
;
167 /* returns LONG_MAX iff out of memory */
168 static PQhandle
__gl_pqHeapInsert( PriorityQHeap
*pq
, PQkey keyNew
)
171 PQhandle free_handle
;
174 if( (curr
*2) > pq
->max
) {
175 PQnode
*saveNodes
= pq
->nodes
;
176 PQhandleElem
*saveHandles
= pq
->handles
;
178 /* If the heap overflows, double its size. */
180 pq
->nodes
= HeapReAlloc( GetProcessHeap(), 0, pq
->nodes
,
182 ((pq
->max
+ 1) * sizeof( pq
->nodes
[0] )));
183 if (pq
->nodes
== NULL
) {
184 pq
->nodes
= saveNodes
; /* restore ptr to free upon return */
187 pq
->handles
= HeapReAlloc( GetProcessHeap(), 0, pq
->handles
,
190 sizeof( pq
->handles
[0] )));
191 if (pq
->handles
== NULL
) {
192 pq
->handles
= saveHandles
; /* restore ptr to free upon return */
197 if( pq
->freeList
== 0 ) {
200 free_handle
= pq
->freeList
;
201 pq
->freeList
= pq
->handles
[free_handle
].node
;
204 pq
->nodes
[curr
].handle
= free_handle
;
205 pq
->handles
[free_handle
].node
= curr
;
206 pq
->handles
[free_handle
].key
= keyNew
;
208 if( pq
->initialized
) {
211 assert(free_handle
!= LONG_MAX
);
215 static PQkey
__gl_pqHeapExtractMin( PriorityQHeap
*pq
)
217 PQnode
*n
= pq
->nodes
;
218 PQhandleElem
*h
= pq
->handles
;
219 PQhandle hMin
= n
[1].handle
;
220 PQkey min
= h
[hMin
].key
;
223 n
[1].handle
= n
[pq
->size
].handle
;
224 h
[n
[1].handle
].node
= 1;
227 h
[hMin
].node
= pq
->freeList
;
230 if( -- pq
->size
> 0 ) {
237 static void __gl_pqHeapDelete( PriorityQHeap
*pq
, PQhandle hCurr
)
239 PQnode
*n
= pq
->nodes
;
240 PQhandleElem
*h
= pq
->handles
;
243 assert( hCurr
>= 1 && hCurr
<= pq
->max
&& h
[hCurr
].key
!= NULL
);
245 curr
= h
[hCurr
].node
;
246 n
[curr
].handle
= n
[pq
->size
].handle
;
247 h
[n
[curr
].handle
].node
= curr
;
249 if( curr
<= -- pq
->size
) {
250 if( curr
<= 1 || LEQ( h
[n
[curr
>>1].handle
].key
, h
[n
[curr
].handle
].key
)) {
251 FloatDown( pq
, curr
);
257 h
[hCurr
].node
= pq
->freeList
;
258 pq
->freeList
= hCurr
;
261 /* Now redefine all the function names to map to their "Sort" versions. */
263 struct PriorityQSort
{
269 int (*leq
)(PQkey key1
, PQkey key2
);
272 PriorityQSort
*__gl_pqSortNewPriorityQ( int (*leq
)(PQkey key1
, PQkey key2
) )
274 PriorityQSort
*pq
= HeapAlloc( GetProcessHeap(), 0, sizeof( PriorityQSort
));
275 if (pq
== NULL
) return NULL
;
277 pq
->heap
= __gl_pqHeapNewPriorityQ( leq
);
278 if (pq
->heap
== NULL
) {
279 HeapFree( GetProcessHeap(), 0, pq
);
283 pq
->keys
= HeapAlloc( GetProcessHeap(), 0, INIT_SIZE
* sizeof(pq
->keys
[0]) );
284 if (pq
->keys
== NULL
) {
285 __gl_pqHeapDeletePriorityQ(pq
->heap
);
286 HeapFree( GetProcessHeap(), 0, pq
);
292 pq
->initialized
= FALSE
;
297 void __gl_pqSortDeletePriorityQ( PriorityQSort
*pq
)
300 if (pq
->heap
!= NULL
) __gl_pqHeapDeletePriorityQ( pq
->heap
);
301 HeapFree( GetProcessHeap(), 0, pq
->order
);
302 HeapFree( GetProcessHeap(), 0, pq
->keys
);
303 HeapFree( GetProcessHeap(), 0, pq
);
307 #define LT(x,y) (! LEQ(y,x))
308 #define GT(x,y) (! LEQ(x,y))
309 #define Swap(a,b) do{PQkey *tmp = *a; *a = *b; *b = tmp;}while(0)
311 int __gl_pqSortInit( PriorityQSort
*pq
)
313 PQkey
**p
, **r
, **i
, **j
, *piv
;
314 struct { PQkey
**p
, **r
; } Stack
[50], *top
= Stack
;
315 unsigned long seed
= 2016473283;
317 /* Create an array of indirect pointers to the keys, so that we
318 * the handles we have returned are still valid.
320 pq
->order
= HeapAlloc( GetProcessHeap(), 0, (size_t)
321 (pq
->size
* sizeof(pq
->order
[0])) );
322 if (pq
->order
== NULL
) return 0;
325 r
= p
+ pq
->size
- 1;
326 for( piv
= pq
->keys
, i
= p
; i
<= r
; ++piv
, ++i
) {
330 /* Sort the indirect pointers in descending order,
331 * using randomized Quicksort
333 top
->p
= p
; top
->r
= r
; ++top
;
334 while( --top
>= Stack
) {
337 while( r
> p
+ 10 ) {
338 seed
= seed
* 1539415821 + 1;
339 i
= p
+ seed
% (r
- p
+ 1);
346 do { ++i
; } while( GT( **i
, *piv
));
347 do { --j
; } while( LT( **j
, *piv
));
350 Swap( i
, j
); /* Undo last swap */
351 if( i
- p
< r
- j
) {
352 top
->p
= j
+1; top
->r
= r
; ++top
;
355 top
->p
= p
; top
->r
= i
-1; ++top
;
359 /* Insertion sort small lists */
360 for( i
= p
+1; i
<= r
; ++i
) {
362 for( j
= i
; j
> p
&& LT( **(j
-1), *piv
); --j
) {
369 pq
->initialized
= TRUE
;
370 __gl_pqHeapInit( pq
->heap
); /* always succeeds */
374 r
= p
+ pq
->size
- 1;
375 for( i
= p
; i
< r
; ++i
) {
376 assert( LEQ( **(i
+1), **i
));
383 /* returns LONG_MAX iff out of memory */
384 PQhandle
__gl_pqSortInsert( PriorityQSort
*pq
, PQkey keyNew
)
388 if( pq
->initialized
) {
389 return __gl_pqHeapInsert( pq
->heap
, keyNew
);
392 if( ++ pq
->size
>= pq
->max
) {
393 PQkey
*saveKey
= pq
->keys
;
395 /* If the heap overflows, double its size. */
397 pq
->keys
= HeapReAlloc( GetProcessHeap(), 0, pq
->keys
,
399 (pq
->max
* sizeof( pq
->keys
[0] )));
400 if (pq
->keys
== NULL
) {
401 pq
->keys
= saveKey
; /* restore ptr to free upon return */
405 assert(curr
!= LONG_MAX
);
406 pq
->keys
[curr
] = keyNew
;
408 /* Negative handles index the sorted array. */
412 PQkey
__gl_pqSortExtractMin( PriorityQSort
*pq
)
414 PQkey sortMin
, heapMin
;
416 if( pq
->size
== 0 ) {
417 return __gl_pqHeapExtractMin( pq
->heap
);
419 sortMin
= *(pq
->order
[pq
->size
-1]);
420 if( ! __gl_pqHeapIsEmpty( pq
->heap
)) {
421 heapMin
= __gl_pqHeapMinimum( pq
->heap
);
422 if( LEQ( heapMin
, sortMin
)) {
423 return __gl_pqHeapExtractMin( pq
->heap
);
428 } while( pq
->size
> 0 && *(pq
->order
[pq
->size
-1]) == NULL
);
432 PQkey
__gl_pqSortMinimum( PriorityQSort
*pq
)
434 PQkey sortMin
, heapMin
;
436 if( pq
->size
== 0 ) {
437 return __gl_pqHeapMinimum( pq
->heap
);
439 sortMin
= *(pq
->order
[pq
->size
-1]);
440 if( ! __gl_pqHeapIsEmpty( pq
->heap
)) {
441 heapMin
= __gl_pqHeapMinimum( pq
->heap
);
442 if( LEQ( heapMin
, sortMin
)) {
449 int __gl_pqSortIsEmpty( PriorityQSort
*pq
)
451 return (pq
->size
== 0) && __gl_pqHeapIsEmpty( pq
->heap
);
454 void __gl_pqSortDelete( PriorityQSort
*pq
, PQhandle curr
)
457 __gl_pqHeapDelete( pq
->heap
, curr
);
461 assert( curr
< pq
->max
&& pq
->keys
[curr
] != NULL
);
463 pq
->keys
[curr
] = NULL
;
464 while( pq
->size
> 0 && *(pq
->order
[pq
->size
-1]) == NULL
) {