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 "gluos.h"
36f220fa62Smrg#include <stddef.h>
37f220fa62Smrg#include <assert.h>
38f220fa62Smrg#include <limits.h>		/* LONG_MAX */
39f220fa62Smrg#include "memalloc.h"
40f220fa62Smrg
41f220fa62Smrg/* Include all the code for the regular heap-based queue here. */
42f220fa62Smrg
43f220fa62Smrg#include "priorityq-heap.c"
44f220fa62Smrg
45f220fa62Smrg/* Now redefine all the function names to map to their "Sort" versions. */
46f220fa62Smrg
47f220fa62Smrg#include "priorityq-sort.h"
48f220fa62Smrg
49f220fa62Smrg/* really __gl_pqSortNewPriorityQ */
50f220fa62SmrgPriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) )
51f220fa62Smrg{
52f220fa62Smrg  PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ ));
53f220fa62Smrg  if (pq == NULL) return NULL;
54f220fa62Smrg
55f220fa62Smrg  pq->heap = __gl_pqHeapNewPriorityQ( leq );
56f220fa62Smrg  if (pq->heap == NULL) {
57f220fa62Smrg     memFree(pq);
58f220fa62Smrg     return NULL;
59f220fa62Smrg  }
60f220fa62Smrg
61f220fa62Smrg  pq->keys = (PQHeapKey *)memAlloc( INIT_SIZE * sizeof(pq->keys[0]) );
62f220fa62Smrg  if (pq->keys == NULL) {
63f220fa62Smrg     __gl_pqHeapDeletePriorityQ(pq->heap);
64f220fa62Smrg     memFree(pq);
65f220fa62Smrg     return NULL;
66f220fa62Smrg  }
67f220fa62Smrg
68e7980a23Smrg  pq->order = NULL;
69f220fa62Smrg  pq->size = 0;
70f220fa62Smrg  pq->max = INIT_SIZE;
71f220fa62Smrg  pq->initialized = FALSE;
72f220fa62Smrg  pq->leq = leq;
73f220fa62Smrg  return pq;
74f220fa62Smrg}
75f220fa62Smrg
76f220fa62Smrg/* really __gl_pqSortDeletePriorityQ */
77f220fa62Smrgvoid pqDeletePriorityQ( PriorityQ *pq )
78f220fa62Smrg{
79f220fa62Smrg  assert(pq != NULL);
80f220fa62Smrg  if (pq->heap != NULL) __gl_pqHeapDeletePriorityQ( pq->heap );
81f220fa62Smrg  if (pq->order != NULL) memFree( pq->order );
82f220fa62Smrg  if (pq->keys != NULL) memFree( pq->keys );
83f220fa62Smrg  memFree( pq );
84f220fa62Smrg}
85f220fa62Smrg
86f220fa62Smrg
87f220fa62Smrg#define LT(x,y)		(! LEQ(y,x))
88f220fa62Smrg#define GT(x,y)		(! LEQ(x,y))
89f220fa62Smrg#define Swap(a,b)	do{PQkey *tmp = *a; *a = *b; *b = tmp;}while(0)
90f220fa62Smrg
91f220fa62Smrg/* really __gl_pqSortInit */
92f220fa62Smrgint pqInit( PriorityQ *pq )
93f220fa62Smrg{
94f220fa62Smrg  PQkey **p, **r, **i, **j, *piv;
95f220fa62Smrg  struct { PQkey **p, **r; } Stack[50], *top = Stack;
96f220fa62Smrg  unsigned long seed = 2016473283;
97f220fa62Smrg
98f220fa62Smrg  /* Create an array of indirect pointers to the keys, so that we
99f220fa62Smrg   * the handles we have returned are still valid.
100f220fa62Smrg   */
101f220fa62Smrg/*
102f220fa62Smrg  pq->order = (PQHeapKey **)memAlloc( (size_t)
103f220fa62Smrg                                  (pq->size * sizeof(pq->order[0])) );
104f220fa62Smrg*/
105f220fa62Smrg  pq->order = (PQHeapKey **)memAlloc( (size_t)
106f220fa62Smrg                                  ((pq->size+1) * sizeof(pq->order[0])) );
107f220fa62Smrg/* the previous line is a patch to compensate for the fact that IBM */
108f220fa62Smrg/* machines return a null on a malloc of zero bytes (unlike SGI),   */
109f220fa62Smrg/* so we have to put in this defense to guard against a memory      */
110f220fa62Smrg/* fault four lines down. from fossum@austin.ibm.com.               */
111f220fa62Smrg  if (pq->order == NULL) return 0;
112f220fa62Smrg
113f220fa62Smrg  p = pq->order;
114f220fa62Smrg  r = p + pq->size - 1;
115f220fa62Smrg  for( piv = pq->keys, i = p; i <= r; ++piv, ++i ) {
116f220fa62Smrg    *i = piv;
117f220fa62Smrg  }
118f220fa62Smrg
119f220fa62Smrg  /* Sort the indirect pointers in descending order,
120f220fa62Smrg   * using randomized Quicksort
121f220fa62Smrg   */
122f220fa62Smrg  top->p = p; top->r = r; ++top;
123f220fa62Smrg  while( --top >= Stack ) {
124f220fa62Smrg    p = top->p;
125f220fa62Smrg    r = top->r;
126f220fa62Smrg    while( r > p + 10 ) {
127f220fa62Smrg      seed = seed * 1539415821 + 1;
128f220fa62Smrg      i = p + seed % (r - p + 1);
129f220fa62Smrg      piv = *i;
130f220fa62Smrg      *i = *p;
131f220fa62Smrg      *p = piv;
132f220fa62Smrg      i = p - 1;
133f220fa62Smrg      j = r + 1;
134f220fa62Smrg      do {
135f220fa62Smrg	do { ++i; } while( GT( **i, *piv ));
136f220fa62Smrg	do { --j; } while( LT( **j, *piv ));
137f220fa62Smrg	Swap( i, j );
138f220fa62Smrg      } while( i < j );
139f220fa62Smrg      Swap( i, j );	/* Undo last swap */
140f220fa62Smrg      if( i - p < r - j ) {
141f220fa62Smrg	top->p = j+1; top->r = r; ++top;
142f220fa62Smrg	r = i-1;
143f220fa62Smrg      } else {
144f220fa62Smrg	top->p = p; top->r = i-1; ++top;
145f220fa62Smrg	p = j+1;
146f220fa62Smrg      }
147f220fa62Smrg    }
148f220fa62Smrg    /* Insertion sort small lists */
149f220fa62Smrg    for( i = p+1; i <= r; ++i ) {
150f220fa62Smrg      piv = *i;
151f220fa62Smrg      for( j = i; j > p && LT( **(j-1), *piv ); --j ) {
152f220fa62Smrg	*j = *(j-1);
153f220fa62Smrg      }
154f220fa62Smrg      *j = piv;
155f220fa62Smrg    }
156f220fa62Smrg  }
157f220fa62Smrg  pq->max = pq->size;
158f220fa62Smrg  pq->initialized = TRUE;
159f220fa62Smrg  __gl_pqHeapInit( pq->heap );	/* always succeeds */
160f220fa62Smrg
161f220fa62Smrg#ifndef NDEBUG
162f220fa62Smrg  p = pq->order;
163f220fa62Smrg  r = p + pq->size - 1;
164f220fa62Smrg  for( i = p; i < r; ++i ) {
165f220fa62Smrg    assert( LEQ( **(i+1), **i ));
166f220fa62Smrg  }
167f220fa62Smrg#endif
168f220fa62Smrg
169f220fa62Smrg  return 1;
170f220fa62Smrg}
171f220fa62Smrg
172f220fa62Smrg/* really __gl_pqSortInsert */
173f220fa62Smrg/* returns LONG_MAX iff out of memory */
174f220fa62SmrgPQhandle pqInsert( PriorityQ *pq, PQkey keyNew )
175f220fa62Smrg{
176f220fa62Smrg  long curr;
177f220fa62Smrg
178f220fa62Smrg  if( pq->initialized ) {
179f220fa62Smrg    return __gl_pqHeapInsert( pq->heap, keyNew );
180f220fa62Smrg  }
181f220fa62Smrg  curr = pq->size;
182f220fa62Smrg  if( ++ pq->size >= pq->max ) {
183f220fa62Smrg    PQkey *saveKey= pq->keys;
184f220fa62Smrg
185f220fa62Smrg    /* If the heap overflows, double its size. */
186f220fa62Smrg    pq->max <<= 1;
187f220fa62Smrg    pq->keys = (PQHeapKey *)memRealloc( pq->keys,
188f220fa62Smrg	 	                        (size_t)
189f220fa62Smrg	                                 (pq->max * sizeof( pq->keys[0] )));
190f220fa62Smrg    if (pq->keys == NULL) {
191f220fa62Smrg       pq->keys = saveKey;	/* restore ptr to free upon return */
192f220fa62Smrg       return LONG_MAX;
193f220fa62Smrg    }
194f220fa62Smrg  }
195f220fa62Smrg  assert(curr != LONG_MAX);
196f220fa62Smrg  pq->keys[curr] = keyNew;
197f220fa62Smrg
198f220fa62Smrg  /* Negative handles index the sorted array. */
199f220fa62Smrg  return -(curr+1);
200f220fa62Smrg}
201f220fa62Smrg
202f220fa62Smrg/* really __gl_pqSortExtractMin */
203f220fa62SmrgPQkey pqExtractMin( PriorityQ *pq )
204f220fa62Smrg{
205f220fa62Smrg  PQkey sortMin, heapMin;
206f220fa62Smrg
207f220fa62Smrg  if( pq->size == 0 ) {
208f220fa62Smrg    return __gl_pqHeapExtractMin( pq->heap );
209f220fa62Smrg  }
210f220fa62Smrg  sortMin = *(pq->order[pq->size-1]);
211f220fa62Smrg  if( ! __gl_pqHeapIsEmpty( pq->heap )) {
212f220fa62Smrg    heapMin = __gl_pqHeapMinimum( pq->heap );
213f220fa62Smrg    if( LEQ( heapMin, sortMin )) {
214f220fa62Smrg      return __gl_pqHeapExtractMin( pq->heap );
215f220fa62Smrg    }
216f220fa62Smrg  }
217f220fa62Smrg  do {
218f220fa62Smrg    -- pq->size;
219f220fa62Smrg  } while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL );
220f220fa62Smrg  return sortMin;
221f220fa62Smrg}
222f220fa62Smrg
223f220fa62Smrg/* really __gl_pqSortMinimum */
224f220fa62SmrgPQkey pqMinimum( PriorityQ *pq )
225f220fa62Smrg{
226f220fa62Smrg  PQkey sortMin, heapMin;
227f220fa62Smrg
228f220fa62Smrg  if( pq->size == 0 ) {
229f220fa62Smrg    return __gl_pqHeapMinimum( pq->heap );
230f220fa62Smrg  }
231f220fa62Smrg  sortMin = *(pq->order[pq->size-1]);
232f220fa62Smrg  if( ! __gl_pqHeapIsEmpty( pq->heap )) {
233f220fa62Smrg    heapMin = __gl_pqHeapMinimum( pq->heap );
234f220fa62Smrg    if( LEQ( heapMin, sortMin )) {
235f220fa62Smrg      return heapMin;
236f220fa62Smrg    }
237f220fa62Smrg  }
238f220fa62Smrg  return sortMin;
239f220fa62Smrg}
240f220fa62Smrg
241f220fa62Smrg/* really __gl_pqSortIsEmpty */
242f220fa62Smrgint pqIsEmpty( PriorityQ *pq )
243f220fa62Smrg{
244f220fa62Smrg  return (pq->size == 0) && __gl_pqHeapIsEmpty( pq->heap );
245f220fa62Smrg}
246f220fa62Smrg
247f220fa62Smrg/* really __gl_pqSortDelete */
248f220fa62Smrgvoid pqDelete( PriorityQ *pq, PQhandle curr )
249f220fa62Smrg{
250f220fa62Smrg  if( curr >= 0 ) {
251f220fa62Smrg    __gl_pqHeapDelete( pq->heap, curr );
252f220fa62Smrg    return;
253f220fa62Smrg  }
254f220fa62Smrg  curr = -(curr+1);
255f220fa62Smrg  assert( curr < pq->max && pq->keys[curr] != NULL );
256f220fa62Smrg
257f220fa62Smrg  pq->keys[curr] = NULL;
258f220fa62Smrg  while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ) {
259f220fa62Smrg    -- pq->size;
260f220fa62Smrg  }
261f220fa62Smrg}
262